@switchbot/openapi-cli 1.0.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/LICENSE +21 -0
- package/README.md +278 -0
- package/dist/api/client.d.ts +12 -0
- package/dist/api/client.js +95 -0
- package/dist/api/client.js.map +1 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +21 -0
- package/dist/auth.js.map +1 -0
- package/dist/commands/completion.d.ts +2 -0
- package/dist/commands/completion.js +259 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +37 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/devices.d.ts +2 -0
- package/dist/commands/devices.js +402 -0
- package/dist/commands/devices.js.map +1 -0
- package/dist/commands/scenes.d.ts +2 -0
- package/dist/commands/scenes.js +57 -0
- package/dist/commands/scenes.js.map +1 -0
- package/dist/commands/webhook.d.ts +2 -0
- package/dist/commands/webhook.js +167 -0
- package/dist/commands/webhook.js.map +1 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +77 -0
- package/dist/config.js.map +1 -0
- package/dist/devices/catalog.d.ts +21 -0
- package/dist/devices/catalog.js +391 -0
- package/dist/devices/catalog.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/flags.d.ts +10 -0
- package/dist/utils/flags.js +34 -0
- package/dist/utils/flags.js.map +1 -0
- package/dist/utils/output.d.ts +5 -0
- package/dist/utils/output.js +78 -0
- package/dist/utils/output.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read global flags directly from process.argv (same pattern as isJsonMode).
|
|
3
|
+
* Kept simple so subcommand actions don't need to thread program.opts() down.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isVerbose(): boolean;
|
|
6
|
+
export declare function isDryRun(): boolean;
|
|
7
|
+
/** HTTP request timeout in milliseconds. Default 30s. */
|
|
8
|
+
export declare function getTimeout(): number;
|
|
9
|
+
/** Override for the credentials file path. */
|
|
10
|
+
export declare function getConfigPath(): string | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read global flags directly from process.argv (same pattern as isJsonMode).
|
|
3
|
+
* Kept simple so subcommand actions don't need to thread program.opts() down.
|
|
4
|
+
*/
|
|
5
|
+
function getFlagValue(...flagNames) {
|
|
6
|
+
for (const flag of flagNames) {
|
|
7
|
+
const idx = process.argv.indexOf(flag);
|
|
8
|
+
if (idx !== -1 && idx + 1 < process.argv.length) {
|
|
9
|
+
return process.argv[idx + 1];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
export function isVerbose() {
|
|
15
|
+
return process.argv.includes('--verbose') || process.argv.includes('-v');
|
|
16
|
+
}
|
|
17
|
+
export function isDryRun() {
|
|
18
|
+
return process.argv.includes('--dry-run');
|
|
19
|
+
}
|
|
20
|
+
/** HTTP request timeout in milliseconds. Default 30s. */
|
|
21
|
+
export function getTimeout() {
|
|
22
|
+
const v = getFlagValue('--timeout');
|
|
23
|
+
if (!v)
|
|
24
|
+
return 30_000;
|
|
25
|
+
const n = Number(v);
|
|
26
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
27
|
+
return 30_000;
|
|
28
|
+
return n;
|
|
29
|
+
}
|
|
30
|
+
/** Override for the credentials file path. */
|
|
31
|
+
export function getConfigPath() {
|
|
32
|
+
return getFlagValue('--config');
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=flags.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../../src/utils/flags.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,SAAS,YAAY,CAAC,GAAG,SAAmB;IAC1C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAChD,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,UAAU;IACxB,MAAM,CAAC,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACtB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACjD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,aAAa;IAC3B,OAAO,YAAY,CAAC,UAAU,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function isJsonMode(): boolean;
|
|
2
|
+
export declare function printJson(data: unknown): void;
|
|
3
|
+
export declare function printTable(headers: string[], rows: (string | number | boolean | null | undefined)[][]): void;
|
|
4
|
+
export declare function printKeyValue(data: Record<string, unknown>): void;
|
|
5
|
+
export declare function handleError(error: unknown): never;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Table from 'cli-table3';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { ApiError, DryRunSignal } from '../api/client.js';
|
|
4
|
+
export function isJsonMode() {
|
|
5
|
+
return process.argv.includes('--json');
|
|
6
|
+
}
|
|
7
|
+
export function printJson(data) {
|
|
8
|
+
console.log(JSON.stringify(data, null, 2));
|
|
9
|
+
}
|
|
10
|
+
export function printTable(headers, rows) {
|
|
11
|
+
const table = new Table({
|
|
12
|
+
head: headers.map((h) => chalk.cyan(h)),
|
|
13
|
+
style: { border: ['grey'] },
|
|
14
|
+
});
|
|
15
|
+
for (const row of rows) {
|
|
16
|
+
table.push(row.map((cell) => {
|
|
17
|
+
if (cell === null || cell === undefined)
|
|
18
|
+
return chalk.grey('—');
|
|
19
|
+
if (typeof cell === 'boolean')
|
|
20
|
+
return cell ? chalk.green('✓') : chalk.red('✗');
|
|
21
|
+
return String(cell);
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
console.log(table.toString());
|
|
25
|
+
}
|
|
26
|
+
export function printKeyValue(data) {
|
|
27
|
+
const table = new Table({
|
|
28
|
+
style: { border: ['grey'] },
|
|
29
|
+
});
|
|
30
|
+
for (const [key, value] of Object.entries(data)) {
|
|
31
|
+
if (value === null || value === undefined)
|
|
32
|
+
continue;
|
|
33
|
+
const displayValue = typeof value === 'object'
|
|
34
|
+
? JSON.stringify(value)
|
|
35
|
+
: String(value);
|
|
36
|
+
table.push({ [chalk.cyan(key)]: displayValue });
|
|
37
|
+
}
|
|
38
|
+
console.log(table.toString());
|
|
39
|
+
}
|
|
40
|
+
export function handleError(error) {
|
|
41
|
+
if (error instanceof DryRunSignal) {
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
if (error instanceof ApiError) {
|
|
45
|
+
console.error(chalk.red(`Error (code ${error.code}): ${error.message}`));
|
|
46
|
+
const hint = errorHint(error.code);
|
|
47
|
+
if (hint)
|
|
48
|
+
console.error(chalk.grey(`Hint: ${hint}`));
|
|
49
|
+
}
|
|
50
|
+
else if (error instanceof Error) {
|
|
51
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.error(chalk.red('An unknown error occurred'));
|
|
55
|
+
}
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
function errorHint(code) {
|
|
59
|
+
switch (code) {
|
|
60
|
+
case 152:
|
|
61
|
+
return "Check the deviceId with 'switchbot devices list' (IDs are case-sensitive).";
|
|
62
|
+
case 160:
|
|
63
|
+
return "Run 'switchbot devices describe <deviceId>' to see which commands this device supports.";
|
|
64
|
+
case 161:
|
|
65
|
+
return 'BLE-only devices require a Hub. Check the hub connection and Wi-Fi.';
|
|
66
|
+
case 171:
|
|
67
|
+
return 'The Hub itself is offline — check its power and Wi-Fi.';
|
|
68
|
+
case 190:
|
|
69
|
+
return "Often means the deviceId is wrong or the command/parameter is invalid for this device. Double-check with 'switchbot devices list' and 'switchbot devices describe <deviceId>'. Use --verbose to see the raw API response.";
|
|
70
|
+
case 401:
|
|
71
|
+
return "Re-run 'switchbot config set-token <token> <secret>', or verify SWITCHBOT_TOKEN / SWITCHBOT_SECRET.";
|
|
72
|
+
case 429:
|
|
73
|
+
return 'Daily quota is 10,000 requests/account — retry after midnight UTC.';
|
|
74
|
+
default:
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@switchbot/openapi-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Command-line interface for SwitchBot API v1.1",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"switchbot",
|
|
7
|
+
"cli",
|
|
8
|
+
"iot",
|
|
9
|
+
"smart-home",
|
|
10
|
+
"home-automation",
|
|
11
|
+
"openapi"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "chenliuyun <chenliuyun@onero.com>",
|
|
15
|
+
"homepage": "https://github.com/chenliuyun/switchbot-openapi-cli#readme",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/chenliuyun/switchbot-openapi-cli/issues"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/chenliuyun/switchbot-openapi-cli.git"
|
|
22
|
+
},
|
|
23
|
+
"type": "module",
|
|
24
|
+
"bin": {
|
|
25
|
+
"switchbot": "dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsc",
|
|
40
|
+
"dev": "tsx src/index.ts",
|
|
41
|
+
"start": "node dist/index.js",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"test:coverage": "vitest run --coverage",
|
|
45
|
+
"prepublishOnly": "npm run build && npm test"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"axios": "^1.7.9",
|
|
49
|
+
"chalk": "^5.4.1",
|
|
50
|
+
"cli-table3": "^0.6.5",
|
|
51
|
+
"commander": "^12.1.0",
|
|
52
|
+
"uuid": "^11.0.5"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^22.10.7",
|
|
56
|
+
"@types/uuid": "^10.0.0",
|
|
57
|
+
"@vitest/coverage-v8": "^2.1.9",
|
|
58
|
+
"tsx": "^4.19.2",
|
|
59
|
+
"typescript": "^5.7.3",
|
|
60
|
+
"vitest": "^2.1.9"
|
|
61
|
+
}
|
|
62
|
+
}
|