@orth/cli 0.2.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 ADDED
@@ -0,0 +1,192 @@
1
+ # Orthogonal CLI
2
+
3
+ CLI to access all APIs and agent skills on the Orthogonal platform.
4
+
5
+ ![Demo](demos/demo.gif)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ # Install globally
11
+ npm install -g @orth/cli
12
+
13
+ # Or use npx
14
+ npx @orth/cli <command>
15
+ ```
16
+
17
+ ## Authentication
18
+
19
+ ```bash
20
+ # Login with API key
21
+ orth login --key orth_live_your_key
22
+
23
+ # Or set environment variable
24
+ export ORTHOGONAL_API_KEY=orth_live_your_key
25
+
26
+ # Check auth status
27
+ orth whoami
28
+
29
+ # Logout
30
+ orth logout
31
+ ```
32
+
33
+ ## API Commands
34
+
35
+ ### Search & Browse
36
+
37
+ ```bash
38
+ # Search for APIs
39
+ orth api search "email finder"
40
+ orth api search "web scraping" --limit 20
41
+
42
+ # List all APIs
43
+ orth api list
44
+
45
+ # Show API endpoints
46
+ orth api show hunter
47
+
48
+ # Show endpoint details
49
+ orth api show hunter /v2/domain-search
50
+ ```
51
+
52
+ ### Call APIs
53
+
54
+ ```bash
55
+ # GET request with query params
56
+ orth api run hunter /v2/domain-search -q domain=stripe.com
57
+
58
+ # POST request with body
59
+ orth api run olostep /v1/scrapes --body '{"url": "https://stripe.com"}'
60
+
61
+ # Raw output for piping
62
+ orth api run hunter /v2/domain-search -q domain=stripe.com --raw | jq '.emails'
63
+ ```
64
+
65
+ ### Generate Code
66
+
67
+ ```bash
68
+ # TypeScript (default)
69
+ orth api code hunter /v2/domain-search
70
+
71
+ # Python
72
+ orth api code hunter /v2/domain-search --lang python
73
+
74
+ # cURL
75
+ orth api code hunter /v2/domain-search --lang curl
76
+ ```
77
+
78
+ ### Request an API
79
+
80
+ ```bash
81
+ # Request an API to be added to the platform
82
+ orth api request https://docs.example.com/api -d "Weather data API"
83
+ ```
84
+
85
+ ## Skills Commands
86
+
87
+ ### Browse & Search
88
+
89
+ ```bash
90
+ # List verified & discoverable skills
91
+ orth skills list
92
+
93
+ # Search for skills
94
+ orth skills search "react best practices"
95
+
96
+ # Show skill details
97
+ orth skills show owner/skill-name
98
+ ```
99
+
100
+ ### Install Skills
101
+
102
+ ```bash
103
+ # Install a skill to all supported agents
104
+ orth skills add owner/skill-name
105
+
106
+ # Install for a specific agent only
107
+ orth skills add owner/skill-name --agent cursor
108
+ ```
109
+
110
+ Installs to 7 agent skill directories:
111
+
112
+ | Agent | Directory |
113
+ |-------|-----------|
114
+ | Cursor | `~/.cursor/skills/` |
115
+ | Claude Code | `~/.claude/skills/` |
116
+ | GitHub Copilot | `~/.github/skills/` |
117
+ | Windsurf | `~/.codeium/windsurf/skills/` |
118
+ | Codex | `~/.agents/skills/` |
119
+ | Gemini | `~/.gemini/skills/` |
120
+ | OpenClaw | `~/.openclaw/skills/` |
121
+
122
+ ### Create & Publish Skills
123
+
124
+ ```bash
125
+ # Initialize a new skill from template
126
+ orth skills init my-skill
127
+ orth skills init my-skill --bare # SKILL.md only, no subdirectories
128
+
129
+ # Create a skill from a GitHub repo
130
+ orth skills create https://github.com/owner/repo
131
+ orth skills create owner/repo --path skills/my-skill --ref main
132
+
133
+ # Submit a local skill to the platform
134
+ orth skills submit ./my-skill
135
+ orth skills submit --name "My Skill" --tags "react,testing"
136
+
137
+ # Request verification (required before discoverability)
138
+ orth skills request-verification owner/my-skill
139
+
140
+ # Request a skill to be added (by description or GitHub URL)
141
+ orth skills request "A skill for React testing patterns"
142
+ orth skills request https://github.com/owner/cool-skill
143
+ ```
144
+
145
+ ### Verification Workflow
146
+
147
+ 1. **Submit** your skill → it's on the platform but not publicly visible
148
+ 2. **Request verification** → our team reviews it
149
+ 3. **Once verified** → toggle discoverability on/off from your [dashboard](https://orthogonal.com/dashboard/skills)
150
+
151
+ ## Account
152
+
153
+ ```bash
154
+ # Check balance
155
+ orth balance
156
+
157
+ # View usage
158
+ orth usage --limit 20
159
+ ```
160
+
161
+ ## Shorthand Aliases
162
+
163
+ These top-level commands are aliases for their `orth api` counterparts:
164
+
165
+ ```bash
166
+ orth search "query" # → orth api search "query"
167
+ orth run slug /path # → orth api run slug /path
168
+ orth code slug /path # → orth api code slug /path
169
+ ```
170
+
171
+ ## Development
172
+
173
+ ```bash
174
+ # Install dependencies
175
+ npm install
176
+
177
+ # Build
178
+ npm run build
179
+
180
+ # Watch mode
181
+ npm run dev
182
+
183
+ # Run tests
184
+ npm test
185
+
186
+ # Watch tests
187
+ npm run test:watch
188
+ ```
189
+
190
+ ## License
191
+
192
+ MIT
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Fire-and-forget analytics event for CLI usage tracking.
3
+ * Never blocks, never throws, never shows errors to the user.
4
+ */
5
+ export declare function trackEvent(command: string, args?: Record<string, string | undefined>): void;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.trackEvent = trackEvent;
4
+ const config_js_1 = require("./config.js");
5
+ const CLI_VERSION = process.env.npm_package_version || "0.2.0";
6
+ const BASE_URL = "https://api.orth.sh/v1";
7
+ /**
8
+ * Fire-and-forget analytics event for CLI usage tracking.
9
+ * Never blocks, never throws, never shows errors to the user.
10
+ */
11
+ function trackEvent(command, args) {
12
+ // Don't track if no API key (not authenticated)
13
+ const apiKey = (0, config_js_1.getApiKey)();
14
+ if (!apiKey)
15
+ return;
16
+ const payload = {
17
+ command,
18
+ args: args ? sanitizeArgs(args) : undefined,
19
+ cliVersion: CLI_VERSION,
20
+ os: process.platform,
21
+ nodeVersion: process.version,
22
+ apiKeyPrefix: apiKey.substring(0, 12),
23
+ timestamp: new Date().toISOString(),
24
+ };
25
+ // Fire and forget - don't await, don't catch visible errors
26
+ fetch(`${BASE_URL}/cli/events`, {
27
+ method: "POST",
28
+ headers: {
29
+ Authorization: `Bearer ${apiKey}`,
30
+ "Content-Type": "application/json",
31
+ "x-orthogonal-source": "cli",
32
+ },
33
+ body: JSON.stringify(payload),
34
+ }).catch(() => {
35
+ // Silently ignore - analytics should never affect CLI operation
36
+ });
37
+ }
38
+ /**
39
+ * Remove any potentially sensitive values from args
40
+ */
41
+ function sanitizeArgs(args) {
42
+ const sanitized = {};
43
+ const sensitiveKeys = ["key", "apiKey", "token", "secret", "password"];
44
+ for (const [key, value] of Object.entries(args)) {
45
+ if (sensitiveKeys.some((s) => key.toLowerCase().includes(s))) {
46
+ sanitized[key] = "[REDACTED]";
47
+ }
48
+ else {
49
+ sanitized[key] = value;
50
+ }
51
+ }
52
+ return sanitized;
53
+ }
package/dist/api.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ export declare function apiRequest<T = unknown>(endpoint: string, options?: {
2
+ method?: string;
3
+ body?: unknown;
4
+ }): Promise<T>;
5
+ export interface SearchResponse {
6
+ results: Array<{
7
+ name: string;
8
+ slug: string;
9
+ endpoints: Array<{
10
+ path: string;
11
+ method: string;
12
+ description: string;
13
+ price?: number;
14
+ }>;
15
+ }>;
16
+ count: number;
17
+ apisCount: number;
18
+ }
19
+ export interface DetailsResponse {
20
+ api?: string | {
21
+ name: string;
22
+ slug: string;
23
+ description?: string;
24
+ };
25
+ path?: string;
26
+ method?: string;
27
+ description?: string;
28
+ price?: number | string;
29
+ parameters?: {
30
+ query?: Array<{
31
+ name: string;
32
+ type: string;
33
+ required: boolean;
34
+ description?: string;
35
+ }>;
36
+ body?: Array<{
37
+ name: string;
38
+ type: string;
39
+ required: boolean;
40
+ description?: string;
41
+ }>;
42
+ };
43
+ endpoint?: {
44
+ path: string;
45
+ method: string;
46
+ description?: string;
47
+ price?: number | string;
48
+ queryParams?: Array<{
49
+ name: string;
50
+ type: string;
51
+ required: boolean;
52
+ description?: string;
53
+ }>;
54
+ bodyParams?: Array<{
55
+ name: string;
56
+ type: string;
57
+ required: boolean;
58
+ description?: string;
59
+ }>;
60
+ };
61
+ }
62
+ export interface RunResponse {
63
+ success: boolean;
64
+ data: unknown;
65
+ price?: string;
66
+ priceCents?: number;
67
+ requestId?: string;
68
+ }
69
+ export interface IntegrateResponse {
70
+ api: string;
71
+ path: string;
72
+ snippets: Record<string, string>;
73
+ }
74
+ export declare function search(prompt: string, limit?: number): Promise<SearchResponse>;
75
+ export declare function getDetails(api: string, path: string): Promise<DetailsResponse>;
76
+ export declare function run(api: string, path: string, options?: {
77
+ method?: string;
78
+ query?: Record<string, string>;
79
+ body?: unknown;
80
+ }): Promise<RunResponse>;
81
+ export declare function integrate(api: string, path: string, format?: string): Promise<IntegrateResponse>;
package/dist/api.js ADDED
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.apiRequest = apiRequest;
4
+ exports.search = search;
5
+ exports.getDetails = getDetails;
6
+ exports.run = run;
7
+ exports.integrate = integrate;
8
+ const config_js_1 = require("./config.js");
9
+ const BASE_URL = "https://api.orth.sh/v1";
10
+ async function apiRequest(endpoint, options = {}) {
11
+ const apiKey = (0, config_js_1.requireApiKey)();
12
+ const res = await fetch(`${BASE_URL}${endpoint}`, {
13
+ method: options.method || "GET",
14
+ headers: {
15
+ Authorization: `Bearer ${apiKey}`,
16
+ "Content-Type": "application/json",
17
+ "x-orthogonal-source": "cli",
18
+ },
19
+ body: options.body ? JSON.stringify(options.body) : undefined,
20
+ });
21
+ const data = (await res.json());
22
+ if (!res.ok || data.success === false) {
23
+ // Include more details in error message
24
+ let errorMsg = data.error || `API request failed with status ${res.status}`;
25
+ // Add any additional error details from the response
26
+ if (data.message) {
27
+ errorMsg += `: ${data.message}`;
28
+ }
29
+ if (data.data?.error) {
30
+ errorMsg += ` - ${data.data.error}`;
31
+ if (data.data?.message) {
32
+ errorMsg += `: ${data.data.message}`;
33
+ }
34
+ }
35
+ // Handle Hunter-style errors array
36
+ if (data.data?.errors &&
37
+ Array.isArray(data.data.errors)) {
38
+ const errors = data.data.errors;
39
+ for (const err of errors) {
40
+ if (err.details) {
41
+ errorMsg += `\n → ${err.details}`;
42
+ }
43
+ else if (err.id) {
44
+ errorMsg += `\n → ${err.id}: ${err.code || ""}`;
45
+ }
46
+ }
47
+ }
48
+ if (data.details) {
49
+ errorMsg += `\n Details: ${JSON.stringify(data.details)}`;
50
+ }
51
+ throw new Error(errorMsg);
52
+ }
53
+ // Return the whole response, not just data field
54
+ return data;
55
+ }
56
+ async function search(prompt, limit = 10) {
57
+ return apiRequest("/search", {
58
+ method: "POST",
59
+ body: { prompt, limit },
60
+ });
61
+ }
62
+ async function getDetails(api, path) {
63
+ return apiRequest("/details", {
64
+ method: "POST",
65
+ body: { api, path },
66
+ });
67
+ }
68
+ async function run(api, path, options = {}) {
69
+ return apiRequest("/run", {
70
+ method: "POST",
71
+ body: {
72
+ api,
73
+ path,
74
+ method: options.method || "GET",
75
+ query: options.query,
76
+ body: options.body,
77
+ },
78
+ });
79
+ }
80
+ async function integrate(api, path, format = "orth-sdk") {
81
+ return apiRequest("/integrate", {
82
+ method: "POST",
83
+ body: { api, path, format },
84
+ });
85
+ }
@@ -0,0 +1,4 @@
1
+ export declare function balanceCommand(): Promise<void>;
2
+ export declare function usageCommand(options: {
3
+ limit: string;
4
+ }): Promise<void>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.balanceCommand = balanceCommand;
7
+ exports.usageCommand = usageCommand;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const api_js_1 = require("../api.js");
11
+ async function balanceCommand() {
12
+ const spinner = (0, ora_1.default)("Fetching balance...").start();
13
+ try {
14
+ // Note: This endpoint may not exist yet - placeholder
15
+ const data = await (0, api_js_1.apiRequest)("/account/balance");
16
+ spinner.stop();
17
+ if (data && data.balance !== undefined) {
18
+ console.log(chalk_1.default.bold("\nAccount Balance:"));
19
+ console.log(chalk_1.default.green.bold(` $${data.balance.toFixed(2)} ${data.currency || "USD"}`));
20
+ }
21
+ else {
22
+ console.log(chalk_1.default.gray("Balance information not available."));
23
+ console.log(chalk_1.default.gray("Check your balance at: https://orthogonal.com/dashboard"));
24
+ }
25
+ }
26
+ catch (error) {
27
+ spinner.stop();
28
+ // Graceful fallback if endpoint doesn't exist
29
+ console.log(chalk_1.default.gray("Balance information not available via API."));
30
+ console.log(chalk_1.default.gray("Check your balance at: https://orthogonal.com/dashboard"));
31
+ }
32
+ }
33
+ async function usageCommand(options) {
34
+ const spinner = (0, ora_1.default)("Fetching usage...").start();
35
+ try {
36
+ // Note: This endpoint may not exist yet - placeholder
37
+ const data = await (0, api_js_1.apiRequest)(`/account/usage?limit=${options.limit}`);
38
+ spinner.stop();
39
+ if (data?.usage && data.usage.length > 0) {
40
+ console.log(chalk_1.default.bold("\nRecent API Usage:\n"));
41
+ for (const item of data.usage) {
42
+ const date = new Date(item.timestamp).toLocaleString();
43
+ console.log(chalk_1.default.gray(date.padEnd(22)) +
44
+ chalk_1.default.cyan(item.api.padEnd(15)) +
45
+ chalk_1.default.white(item.path.padEnd(30)) +
46
+ chalk_1.default.green(`$${item.cost.toFixed(4)}`));
47
+ }
48
+ console.log(chalk_1.default.bold(`\nTotal: $${data.total.toFixed(2)}`));
49
+ }
50
+ else {
51
+ console.log(chalk_1.default.gray("No recent usage data available."));
52
+ }
53
+ }
54
+ catch (error) {
55
+ spinner.stop();
56
+ // Graceful fallback if endpoint doesn't exist
57
+ console.log(chalk_1.default.gray("Usage information not available via API."));
58
+ console.log(chalk_1.default.gray("Check your usage at: https://orthogonal.com/dashboard/usage"));
59
+ }
60
+ }
@@ -0,0 +1,6 @@
1
+ interface ApiOptions {
2
+ x402?: boolean;
3
+ x402Full?: boolean;
4
+ }
5
+ export declare function apiCommand(slug?: string, path?: string, options?: ApiOptions): Promise<void>;
6
+ export {};
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.apiCommand = apiCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const api_js_1 = require("../api.js");
10
+ async function apiCommand(slug, path, options) {
11
+ const spinner = (0, ora_1.default)("Loading...").start();
12
+ try {
13
+ if (!slug) {
14
+ // List all APIs - search multiple terms to get broader coverage
15
+ const searches = await Promise.all([
16
+ (0, api_js_1.search)("api", 50),
17
+ (0, api_js_1.search)("data", 50),
18
+ (0, api_js_1.search)("search", 50),
19
+ (0, api_js_1.search)("email", 50),
20
+ ]);
21
+ spinner.stop();
22
+ // Merge and dedupe results
23
+ const allResults = searches.flatMap(s => s.results || []);
24
+ const data = {
25
+ results: allResults,
26
+ count: allResults.length,
27
+ apisCount: new Set(allResults.map(r => r.slug)).size,
28
+ };
29
+ console.log(chalk_1.default.bold("\nAvailable APIs:\n"));
30
+ const seen = new Set();
31
+ for (const api of data.results) {
32
+ if (!api.slug || seen.has(api.slug))
33
+ continue;
34
+ seen.add(api.slug);
35
+ console.log(chalk_1.default.cyan.bold(api.slug.padEnd(20)) +
36
+ chalk_1.default.white(api.name || "") +
37
+ chalk_1.default.gray(` (${api.endpoints?.length || 0} endpoints)`));
38
+ }
39
+ console.log(chalk_1.default.gray("\nRun 'orth api <slug>' to see endpoints for an API"));
40
+ return;
41
+ }
42
+ if (path) {
43
+ // Show endpoint details
44
+ const data = await (0, api_js_1.getDetails)(slug, path);
45
+ spinner.stop();
46
+ console.log(chalk_1.default.bold(`\n${chalk_1.default.cyan(slug)}${chalk_1.default.white(path)}\n`));
47
+ // Get description from endpoint object if available
48
+ const desc = data.description || data.endpoint?.description;
49
+ console.log(chalk_1.default.gray(desc || "No description"));
50
+ // Get price
51
+ const price = data.price || data.endpoint?.price;
52
+ if (price) {
53
+ console.log(chalk_1.default.green(`\nPrice: ${typeof price === 'number' ? '$' + price : price}`));
54
+ }
55
+ // Get params from nested endpoint object if needed
56
+ const queryParams = data.parameters?.query || data.endpoint?.queryParams || [];
57
+ const bodyParams = data.parameters?.body || data.endpoint?.bodyParams || [];
58
+ if (queryParams.length > 0) {
59
+ console.log(chalk_1.default.bold("\nQuery Parameters:"));
60
+ for (const param of queryParams) {
61
+ const required = param.required ? chalk_1.default.red("*") : "";
62
+ console.log(chalk_1.default.yellow(` ${param.name}${required}`) +
63
+ chalk_1.default.gray(` (${param.type})`) +
64
+ (param.description ? chalk_1.default.gray(` - ${param.description}`) : ""));
65
+ }
66
+ }
67
+ if (bodyParams.length > 0) {
68
+ console.log(chalk_1.default.bold("\nBody Parameters:"));
69
+ for (const param of bodyParams) {
70
+ const required = param.required ? chalk_1.default.red("*") : "";
71
+ console.log(chalk_1.default.yellow(` ${param.name}${required}`) +
72
+ chalk_1.default.gray(` (${param.type})`) +
73
+ (param.description ? chalk_1.default.gray(` - ${param.description}`) : ""));
74
+ }
75
+ }
76
+ // Generate appropriate example
77
+ console.log(chalk_1.default.gray("\nExample:"));
78
+ if (bodyParams.length > 0) {
79
+ const exampleBody = {};
80
+ for (const param of bodyParams.slice(0, 3)) {
81
+ exampleBody[param.name] = param.type === 'object' ? '{}' : `<${param.name}>`;
82
+ }
83
+ console.log(chalk_1.default.white(` orth run ${slug} ${path} --body '${JSON.stringify(exampleBody)}'`));
84
+ }
85
+ else if (queryParams.length > 0) {
86
+ const exampleQuery = queryParams.slice(0, 2).map((p) => `-q ${p.name}=<value>`).join(' ');
87
+ console.log(chalk_1.default.white(` orth run ${slug} ${path} ${exampleQuery}`));
88
+ }
89
+ else {
90
+ console.log(chalk_1.default.white(` orth run ${slug} ${path}`));
91
+ }
92
+ // x402 direct payment info
93
+ if (options?.x402 || options?.x402Full) {
94
+ const x402Url = `https://x402.orth.sh/${slug}${path}`;
95
+ // Determine HTTP method: POST if body params, GET otherwise
96
+ const method = bodyParams.length > 0 ? 'POST' : 'GET';
97
+ if (options?.x402 && !options?.x402Full) {
98
+ // Minimal output - just the URL
99
+ console.log(`\n${x402Url}`);
100
+ }
101
+ else {
102
+ // Full output - actually call the endpoint and get the 402 response
103
+ try {
104
+ const fetchOptions = { method };
105
+ if (method === 'POST') {
106
+ fetchOptions.headers = { 'Content-Type': 'application/json' };
107
+ fetchOptions.body = '{}';
108
+ }
109
+ const response = await fetch(x402Url, fetchOptions);
110
+ const responseData = await response.json();
111
+ console.log(chalk_1.default.bold.magenta("\n── x402 Payment Details ──\n"));
112
+ console.log(chalk_1.default.cyan(`URL: ${x402Url}`));
113
+ console.log(chalk_1.default.yellow(`Method: ${method}`));
114
+ console.log(chalk_1.default.gray(`Status: ${response.status}\n`));
115
+ console.log(JSON.stringify(responseData, null, 2));
116
+ }
117
+ catch (err) {
118
+ console.log(chalk_1.default.red(`\nFailed to fetch x402 details: ${err}`));
119
+ }
120
+ }
121
+ }
122
+ return;
123
+ }
124
+ // Show API endpoints
125
+ const data = await (0, api_js_1.search)(slug, 20);
126
+ spinner.stop();
127
+ const api = data.results.find((a) => a.slug === slug);
128
+ if (!api) {
129
+ console.log(chalk_1.default.yellow(`API '${slug}' not found.`));
130
+ console.log(chalk_1.default.gray("Run 'orth api' to see available APIs"));
131
+ return;
132
+ }
133
+ console.log(chalk_1.default.bold(`\n${chalk_1.default.cyan(api.name)} (${api.slug})\n`));
134
+ for (const endpoint of api.endpoints) {
135
+ const method = chalk_1.default.yellow(endpoint.method.padEnd(6));
136
+ const price = endpoint.price ? chalk_1.default.green(`$${endpoint.price.toFixed(2)}`) : chalk_1.default.gray("free");
137
+ console.log(`${method} ${chalk_1.default.white(endpoint.path)} ${price}`);
138
+ if (endpoint.description) {
139
+ console.log(chalk_1.default.gray(` ${endpoint.description.slice(0, 80)}${endpoint.description.length > 80 ? "..." : ""}`));
140
+ }
141
+ }
142
+ console.log(chalk_1.default.gray("\nRun 'orth api " + slug + " <path>' for endpoint details"));
143
+ console.log(chalk_1.default.gray("Run 'orth run " + slug + " <path>' to call an endpoint"));
144
+ }
145
+ catch (error) {
146
+ spinner.stop();
147
+ console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
148
+ process.exit(1);
149
+ }
150
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * orth api request <docsUrl> - Request an API to be added to the platform
3
+ */
4
+ export declare function apiRequestCommand(docsUrl: string, options: {
5
+ description?: string;
6
+ }): Promise<void>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.apiRequestCommand = apiRequestCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const api_js_1 = require("../api.js");
10
+ /**
11
+ * orth api request <docsUrl> - Request an API to be added to the platform
12
+ */
13
+ async function apiRequestCommand(docsUrl, options) {
14
+ const spinner = (0, ora_1.default)("Submitting API request...").start();
15
+ try {
16
+ await (0, api_js_1.apiRequest)("/requests/api", {
17
+ method: "POST",
18
+ body: {
19
+ docsUrl,
20
+ description: options.description,
21
+ },
22
+ });
23
+ spinner.stop();
24
+ console.log(chalk_1.default.green("\n✓ API request submitted!"));
25
+ console.log(chalk_1.default.gray("Our team has been notified and will review your request."));
26
+ console.log(chalk_1.default.gray(` Docs URL: ${docsUrl}`));
27
+ if (options.description) {
28
+ console.log(chalk_1.default.gray(` Notes: ${options.description}`));
29
+ }
30
+ }
31
+ catch (error) {
32
+ spinner.stop();
33
+ console.error(chalk_1.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
34
+ process.exit(1);
35
+ }
36
+ }