@orth/cli 0.2.11 → 0.2.13
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/dist/api.d.ts +9 -0
- package/dist/commands/api.js +5 -4
- package/dist/commands/auth.js +1 -1
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.js +80 -0
- package/dist/config.js +1 -1
- package/dist/index.js +2 -0
- package/package.json +5 -5
package/dist/api.d.ts
CHANGED
|
@@ -58,6 +58,15 @@ export interface DetailsResponse {
|
|
|
58
58
|
description?: string;
|
|
59
59
|
}>;
|
|
60
60
|
};
|
|
61
|
+
action?: {
|
|
62
|
+
description?: string;
|
|
63
|
+
parameters?: Array<{
|
|
64
|
+
name: string;
|
|
65
|
+
type: string;
|
|
66
|
+
required: boolean;
|
|
67
|
+
description?: string;
|
|
68
|
+
}>;
|
|
69
|
+
};
|
|
61
70
|
}
|
|
62
71
|
export interface RunResponse {
|
|
63
72
|
success: boolean;
|
package/dist/commands/api.js
CHANGED
|
@@ -53,12 +53,13 @@ async function apiCommand(slug, path, options) {
|
|
|
53
53
|
const data = await (0, api_js_1.getDetails)(slug, path);
|
|
54
54
|
spinner.stop();
|
|
55
55
|
console.log(chalk_1.default.bold(`\n${chalk_1.default.cyan(slug)}${chalk_1.default.white(path)}\n`));
|
|
56
|
-
// Get description from endpoint object if available
|
|
57
|
-
const desc = data.description || data.endpoint?.description;
|
|
56
|
+
// Get description from endpoint or action object if available
|
|
57
|
+
const desc = data.description || data.endpoint?.description || data.action?.description;
|
|
58
58
|
console.log(chalk_1.default.gray(desc || "No description"));
|
|
59
|
-
// Get params from nested endpoint object if needed
|
|
59
|
+
// Get params from nested endpoint or action object if needed
|
|
60
|
+
const actionParams = data.action?.parameters ?? [];
|
|
60
61
|
const queryParams = data.parameters?.query || data.endpoint?.queryParams || [];
|
|
61
|
-
const bodyParams = data.parameters?.body || data.endpoint?.bodyParams ||
|
|
62
|
+
const bodyParams = data.parameters?.body || data.endpoint?.bodyParams || actionParams;
|
|
62
63
|
if (queryParams.length > 0) {
|
|
63
64
|
console.log(chalk_1.default.bold("\nQuery Parameters:"));
|
|
64
65
|
for (const param of queryParams) {
|
package/dist/commands/auth.js
CHANGED
|
@@ -33,7 +33,7 @@ async function whoamiCommand() {
|
|
|
33
33
|
const key = (0, config_js_1.getApiKey)();
|
|
34
34
|
if (!key) {
|
|
35
35
|
console.log(chalk_1.default.yellow("Not authenticated"));
|
|
36
|
-
console.log(chalk_1.default.gray("Run '
|
|
36
|
+
console.log(chalk_1.default.gray("Run 'orth login' to authenticate"));
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
console.log(chalk_1.default.green("✓ Authenticated"));
|
package/dist/commands/run.d.ts
CHANGED
package/dist/commands/run.js
CHANGED
|
@@ -6,7 +6,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.runCommand = runCommand;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const fs_1 = require("fs");
|
|
10
|
+
const path_1 = require("path");
|
|
9
11
|
const api_js_1 = require("../api.js");
|
|
12
|
+
// Map content-type to file extension
|
|
13
|
+
const CONTENT_TYPE_EXT = {
|
|
14
|
+
"image/jpeg": "jpg",
|
|
15
|
+
"image/png": "png",
|
|
16
|
+
"image/gif": "gif",
|
|
17
|
+
"image/webp": "webp",
|
|
18
|
+
"image/svg+xml": "svg",
|
|
19
|
+
"application/pdf": "pdf",
|
|
20
|
+
"application/zip": "zip",
|
|
21
|
+
"application/octet-stream": "bin",
|
|
22
|
+
"audio/mpeg": "mp3",
|
|
23
|
+
"audio/wav": "wav",
|
|
24
|
+
"video/mp4": "mp4",
|
|
25
|
+
};
|
|
26
|
+
const VALID_ENCODINGS = new Set(["base64", "base64url", "hex", "utf8", "utf-8", "ascii", "latin1", "binary"]);
|
|
27
|
+
function writeExclusive(filePath, data) {
|
|
28
|
+
try {
|
|
29
|
+
(0, fs_1.writeFileSync)(filePath, data, { flag: "wx" });
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err?.code === "EEXIST") {
|
|
33
|
+
console.error(chalk_1.default.red(`\nError: File already exists: ${filePath}`));
|
|
34
|
+
console.error(chalk_1.default.gray("Remove it first or choose a different path."));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function extFromContentType(contentType) {
|
|
41
|
+
// Try exact match first, then prefix match
|
|
42
|
+
if (CONTENT_TYPE_EXT[contentType])
|
|
43
|
+
return CONTENT_TYPE_EXT[contentType];
|
|
44
|
+
// Strip parameters (e.g., "image/jpeg; charset=utf-8")
|
|
45
|
+
const base = contentType.split(";")[0].trim();
|
|
46
|
+
if (CONTENT_TYPE_EXT[base])
|
|
47
|
+
return CONTENT_TYPE_EXT[base];
|
|
48
|
+
// Fallback: use subtype
|
|
49
|
+
const parts = base.split("/");
|
|
50
|
+
return parts[1] || "bin";
|
|
51
|
+
}
|
|
52
|
+
function isBinaryEnvelope(data) {
|
|
53
|
+
return (typeof data === "object" &&
|
|
54
|
+
data !== null &&
|
|
55
|
+
data._binary === true &&
|
|
56
|
+
typeof data.data === "string" &&
|
|
57
|
+
typeof data.encoding === "string" &&
|
|
58
|
+
typeof data.contentType === "string" &&
|
|
59
|
+
typeof data.size === "number");
|
|
60
|
+
}
|
|
10
61
|
async function runCommand(api, path, options) {
|
|
11
62
|
const spinner = (0, ora_1.default)(`Calling ${api}${path}...`).start();
|
|
12
63
|
try {
|
|
@@ -64,6 +115,35 @@ async function runCommand(api, path, options) {
|
|
|
64
115
|
body,
|
|
65
116
|
});
|
|
66
117
|
spinner.stop();
|
|
118
|
+
// Handle binary responses (base64-encoded by the server)
|
|
119
|
+
if (isBinaryEnvelope(result.data)) {
|
|
120
|
+
if (!options.output) {
|
|
121
|
+
const ext = extFromContentType(result.data.contentType);
|
|
122
|
+
const methodHint = options.method !== "GET" ? ` -X ${options.method}` : "";
|
|
123
|
+
const bodyHint = options.body || options.data ? " --body '...'" : "";
|
|
124
|
+
const queryHint = options.query?.length ? " -q '...'" : "";
|
|
125
|
+
console.log(chalk_1.default.yellow(`\nResponse contains binary ${ext.toUpperCase()} data (${result.data.size} bytes).` +
|
|
126
|
+
`\nUse -o to save it: orth api run ${api} ${path}${methodHint}${queryHint}${bodyHint} -o output.${ext}`));
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const ext = extFromContentType(result.data.contentType);
|
|
130
|
+
const outputPath = (0, path_1.resolve)(options.output);
|
|
131
|
+
if (!VALID_ENCODINGS.has(result.data.encoding)) {
|
|
132
|
+
console.error(chalk_1.default.red(`\nError: Server returned unsupported encoding "${result.data.encoding}".`));
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
const buffer = Buffer.from(result.data.data, result.data.encoding);
|
|
136
|
+
writeExclusive(outputPath, buffer);
|
|
137
|
+
console.log(chalk_1.default.green(`\n${ext.toUpperCase()} saved to: ${outputPath} (${buffer.length} bytes)`));
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
// If --output specified for non-binary data, save JSON to file
|
|
141
|
+
if (options.output) {
|
|
142
|
+
const outputPath = (0, path_1.resolve)(options.output);
|
|
143
|
+
writeExclusive(outputPath, JSON.stringify(result.data, null, 2));
|
|
144
|
+
console.log(chalk_1.default.green(`\nResponse saved to: ${outputPath}`));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
67
147
|
if (options.raw) {
|
|
68
148
|
console.log(JSON.stringify(result.data, null, 2));
|
|
69
149
|
}
|
package/dist/config.js
CHANGED
|
@@ -29,7 +29,7 @@ function clearApiKey() {
|
|
|
29
29
|
function requireApiKey() {
|
|
30
30
|
const key = getApiKey();
|
|
31
31
|
if (!key) {
|
|
32
|
-
console.error("Error: Not authenticated. Run '
|
|
32
|
+
console.error("Error: Not authenticated. Run 'orth login' first or set ORTHOGONAL_API_KEY.");
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
return key;
|
package/dist/index.js
CHANGED
|
@@ -110,6 +110,7 @@ apiGroup
|
|
|
110
110
|
.option("-b, --body <json>", "Request body JSON")
|
|
111
111
|
.option("-d, --data <json>", "Alias for --body")
|
|
112
112
|
.option("--raw", "Output raw JSON without formatting")
|
|
113
|
+
.option("-o, --output <file>", "Save response to file (auto-detects binary like images)")
|
|
113
114
|
.action(asyncAction(async (slug, path, options) => {
|
|
114
115
|
(0, analytics_js_1.trackEvent)("api.run", { slug, path });
|
|
115
116
|
await (0, run_js_1.runCommand)(slug, path, options);
|
|
@@ -253,6 +254,7 @@ program
|
|
|
253
254
|
.option("-b, --body <json>", "Request body JSON")
|
|
254
255
|
.option("-d, --data <json>", "Alias for --body")
|
|
255
256
|
.option("--raw", "Output raw JSON without formatting")
|
|
257
|
+
.option("-o, --output <file>", "Save response to file (auto-detects binary like images)")
|
|
256
258
|
.action(asyncAction(async (api, path, options) => {
|
|
257
259
|
(0, analytics_js_1.trackEvent)("run", { api, path });
|
|
258
260
|
await (0, run_js_1.runCommand)(api, path, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orth/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.13",
|
|
4
4
|
"description": "CLI to access all APIs and skills on the Orthogonal platform",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"chalk": "^
|
|
43
|
+
"chalk": "^4.1.2",
|
|
44
44
|
"commander": "^12.0.0",
|
|
45
|
-
"conf": "^
|
|
46
|
-
"node-fetch": "^
|
|
47
|
-
"ora": "^
|
|
45
|
+
"conf": "^10.2.0",
|
|
46
|
+
"node-fetch": "^2.7.0",
|
|
47
|
+
"ora": "^5.4.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^20.0.0",
|