Sign In

otterkit

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

otterkit - npm Package Compare versions

Comparing version
0.46.0
to
0.47.0
+7
-2
dist/history.js

@@ -90,5 +90,6 @@ /**

}
import { c, CROSS, dim } from './ui.js';
import { c, dim, spinner } from './ui.js';
/** `otterkit requests <subdomain>` - print stored history. */
export async function printHistory(subdomain, opts) {
const spin = opts.json ? null : await spinner('Fetching stored history…');
let data;

@@ -108,6 +109,10 @@ try {

else {
console.log(`\n ${CROSS} ${err.message}\n`);
spin?.stop(err.message, true);
console.log('');
}
process.exit(1);
}
spin?.stop(data.requests.length === 0
? dim('No stored requests')
: `${c.bold}${data.requests.length}${c.reset} stored request${data.requests.length === 1 ? '' : 's'}${data.hasMore ? ` ${dim('· more available')}` : ''}`);
if (opts.json) {

@@ -114,0 +119,0 @@ console.log(JSON.stringify(data, null, 2));

@@ -43,3 +43,3 @@ /**

}
import { c, CHECK, CROSS, dim } from './ui.js';
import { c, CHECK, CROSS, dim, label, spinner } from './ui.js';
async function api(path, body, token) {

@@ -103,5 +103,5 @@ const resp = await fetch(`${API_SERVER}${path}`, {

console.log('');
console.log(` ${dim('Waiting for approval in your browser…')}`);
openBrowser(verification_uri_complete);
}
const approvalSpin = json ? null : await spinner('Waiting for approval in your browser…');
const deadline = Date.now() + expires_in * 1000;

@@ -126,4 +126,3 @@ const intervalMs = Math.max(1, interval) * 1000;

}
console.log('');
console.log(` ${CHECK} ${c.bold}Logged in.${c.reset} Agents on this machine can now provision tunnels.`);
approvalSpin?.stop(`${c.bold}Logged in.${c.reset} Agents on this machine can now provision tunnels.`);
console.log(` ${dim('Check your balance with')} ${c.bold}otterkit balance${c.reset}`);

@@ -138,3 +137,4 @@ console.log('');

}
console.log(`\n ${CROSS} Login was denied.\n`);
approvalSpin?.stop('Login was denied.', true);
console.log('');
process.exit(1);

@@ -147,3 +147,4 @@ }

}
console.log(`\n ${CROSS} Login code expired. Run ${c.bold}otterkit login${c.reset} again.\n`);
approvalSpin?.stop(`Login code expired. Run ${c.bold}otterkit login${c.reset} again.`, true);
console.log('');
process.exit(1);

@@ -156,3 +157,4 @@ }

}
console.log(`\n ${CROSS} Login timed out. Run ${c.bold}otterkit login${c.reset} again.\n`);
approvalSpin?.stop(`Login timed out. Run ${c.bold}otterkit login${c.reset} again.`, true);
console.log('');
process.exit(1);

@@ -180,2 +182,3 @@ }

}
const spin = json ? null : await spinner('Fetching account…');
const me = await api('/api/me', undefined, token);

@@ -187,5 +190,7 @@ if (!me.ok || !me.data) {

}
console.log(`\n ${CROSS} ${me.error || 'Could not fetch account'}\n`);
spin?.stop(me.error || 'Could not fetch account', true);
console.log('');
process.exit(1);
}
spin?.stop(`Signed in as ${c.bold}${me.data.email || '(no email)'}${c.reset}`);
const creds = loadCredentials();

@@ -217,2 +222,3 @@ if (json) {

}
const spin = json ? null : await spinner('Fetching balance…');
const res = await api('/api/me/balance', undefined, token);

@@ -224,3 +230,4 @@ if (!res.ok || !res.data) {

}
console.log(`\n ${CROSS} ${res.error || 'Could not fetch balance'}\n`);
spin?.stop(res.error || 'Could not fetch balance', true);
console.log('');
process.exit(1);

@@ -232,8 +239,4 @@ }

}
spin?.stop(`${c.bold}${res.data.balance}${c.reset} credits ${dim(`($${(res.data.balance / 100).toFixed(2)})`)}`);
console.log('');
console.log(` ${c.bold}${res.data.balance}${c.reset} credits ${dim(`($${(res.data.balance / 100).toFixed(2)})`)}`);
console.log('');
}
function label(text) {
return `${c.gray}${text}${c.reset}`;
}

@@ -18,25 +18,3 @@ /**

import { getProvider } from './providers.js';
/* ── ANSI helpers (mirrors index.ts) ── */
const c = {
reset: '\x1b[0m',
bold: '\x1b[1m',
green: '\x1b[32m',
cyan: '\x1b[36m',
yellow: '\x1b[33m',
red: '\x1b[31m',
gray: '\x1b[90m',
white: '\x1b[97m',
};
const CHECK = `${c.green}✓${c.reset}`;
const CROSS = `${c.red}✗${c.reset}`;
const dim = (s) => `${c.gray}${s}${c.reset}`;
function statusBadge(code) {
if (code < 300)
return `${c.green}${code}${c.reset}`;
if (code < 400)
return `${c.cyan}${code}${c.reset}`;
if (code < 500)
return `${c.yellow}${code}${c.reset}`;
return `${c.red}${code}${c.reset}`;
}
import { c, CROSS, dim, statusBadge, spinner } from './ui.js';
// Connection-level headers that must not be copied onto a fresh request.

@@ -274,2 +252,3 @@ const SKIP_HEADERS = new Set([

export async function replayCmd(subdomain, options) {
const spin = options.json ? null : await spinner('Replaying capture…');
let result;

@@ -281,3 +260,8 @@ try {

if (err instanceof ReplayError) {
console.log(`\n ${CROSS} ${c.bold}${err.message}${c.reset}`);
if (options.json) {
console.log(`\n ${CROSS} ${c.bold}${err.message}${c.reset}`);
}
else {
spin?.stop(`${c.bold}${err.message}${c.reset}`, true);
}
if (err.hint)

@@ -302,5 +286,4 @@ console.log(` ${dim(err.hint)}`);

: Buffer.alloc(0);
spin?.stop(`${c.bold}Replayed${c.reset} request #${result.index} ${dim(`of ${result.total}`)} ${c.white}${result.method}${c.reset} ${result.path}`);
console.log('');
console.log(` ${CHECK} ${c.bold}Replayed${c.reset} request #${result.index} ${dim(`of ${result.total}`)} ${c.white}${result.method}${c.reset} ${result.path}`);
console.log('');
console.log(` ${dim('Target')} ${c.white}${result.target}${c.reset}`);

@@ -307,0 +290,0 @@ console.log(` ${dim('Response')} ${statusBadge(result.status)} ${dim(`${result.durationMs}ms · ${respBody.length}B`)}`);

@@ -12,14 +12,3 @@ /**

const API_SERVER = process.env.OTTERKIT_API_URL || 'https://api.otterkit.com';
/* ── ANSI helpers (mirrors index.ts) ── */
const c = {
reset: '\x1b[0m',
bold: '\x1b[1m',
green: '\x1b[32m',
cyan: '\x1b[36m',
red: '\x1b[31m',
gray: '\x1b[90m',
};
const CHECK = `${c.green}✓${c.reset}`;
const CROSS = `${c.red}✗${c.reset}`;
const dim = (s) => `${c.gray}${s}${c.reset}`;
import { c, dim, spinner } from './ui.js';
async function api(method, path, body) {

@@ -56,2 +45,3 @@ const token = getToken();

export async function listSubdomains(json) {
const spin = json ? null : await spinner('Fetching reserved subdomains…');
const { env } = await api('GET', '/api/me/subdomains');

@@ -63,3 +53,4 @@ if (!env.ok || !env.data) {

}
console.log(`\n ${CROSS} ${env.error || 'Could not fetch subdomains'}\n`);
spin?.stop(env.error || 'Could not fetch subdomains', true);
console.log('');
process.exit(1);

@@ -73,2 +64,5 @@ }

}
spin?.stop(list.length === 0
? dim('No reserved subdomains')
: `${c.bold}${list.length}${c.reset} reserved subdomain${list.length === 1 ? '' : 's'} ${dim('· up to 10 per workspace')}`);
console.log('');

@@ -92,2 +86,3 @@ if (list.length === 0) {

export async function reserveSubdomainCmd(name, label) {
const spin = await spinner(`Reserving ${name}…`);
const { status, env } = await api('POST', '/api/me/subdomains', {

@@ -98,27 +93,35 @@ name,

if (status === 409) {
console.log(`\n ${CROSS} ${env.message || `Subdomain "${name}" is not available.`}\n`);
spin.stop(env.message || `Subdomain "${name}" is not available.`, true);
console.log('');
process.exit(1);
}
if (status === 400) {
console.log(`\n ${CROSS} ${env.message || env.error || 'Invalid subdomain'}\n`);
spin.stop(env.message || env.error || 'Invalid subdomain', true);
console.log('');
process.exit(1);
}
if (!env.ok) {
console.log(`\n ${CROSS} ${env.error || 'Could not reserve subdomain'}\n`);
spin.stop(env.error || 'Could not reserve subdomain', true);
console.log('');
process.exit(1);
}
console.log(`\n ${CHECK} Reserved ${c.bold}${c.cyan}${name}.${tunnelHost()}${c.reset}\n`);
spin.stop(`Reserved ${c.bold}${c.cyan}${name}.${tunnelHost()}${c.reset}`);
console.log('');
}
/** `otterkit subdomains release <name>` - release a reserved subdomain. */
export async function releaseSubdomainCmd(name) {
const spin = await spinner(`Releasing ${name}…`);
const { status, env } = await api('DELETE', `/api/me/subdomains/${encodeURIComponent(name)}`);
if (status === 404) {
console.log(`\n ${CROSS} No reserved subdomain named ${c.bold}${name}${c.reset}\n`);
spin.stop(`No reserved subdomain named ${c.bold}${name}${c.reset}`, true);
console.log('');
process.exit(1);
}
if (!env.ok) {
console.log(`\n ${CROSS} ${env.error || 'Could not release subdomain'}\n`);
spin.stop(env.error || 'Could not release subdomain', true);
console.log('');
process.exit(1);
}
console.log(`\n ${CHECK} Released ${c.bold}${name}${c.reset}\n`);
spin.stop(`Released ${c.bold}${name}${c.reset}`);
console.log('');
}

@@ -29,2 +29,7 @@ export declare const c: {

export declare function printBanner(): void;
/**
* The big banner: hand-drawn ASCII wordmark, shown only where users ask to
* see the CLI itself (bare `otterkit`, `--help`) - never in command flows.
*/
export declare function bigBanner(version: string): string;
export interface Spin {

@@ -31,0 +36,0 @@ message(text: string): void;

@@ -59,5 +59,21 @@ /**

console.log('');
console.log(` ${BRAND} ${dim('- instant tunnels & webhooks')}`);
console.log(` ${pc.green('◉')} ${BRAND} ${dim('- instant tunnels & webhooks')}`);
console.log('');
}
/**
* The big banner: hand-drawn ASCII wordmark, shown only where users ask to
* see the CLI itself (bare `otterkit`, `--help`) - never in command flows.
*/
export function bigBanner(version) {
const art = [
' _ _ _ _ _',
' ___ | |_| |_ ___ _ __| | _(_) |_',
" / _ \\| __| __/ _ \\ '__| |/ /| | __|",
'| (_) | |_| || __/ | | < | | |_',
' \\___/ \\__|\\__\\___|_| |_|\\_\\|_|\\__|',
]
.map(line => pc.green(line))
.join('\n');
return `\n${art}\n\n ${pc.bold('webhooks that never sleep · tunnels in one command')}\n ${dim(`v${version} · https://www.otterkit.com/docs`)}\n`;
}
export async function spinner(text) {

@@ -64,0 +80,0 @@ if (!process.stdout.isTTY || process.env.CI) {

@@ -11,16 +11,3 @@ /**

import { initPayment } from './provision.js';
/* ── ANSI helpers (mirrors index.ts) ── */
const c = {
reset: '\x1b[0m',
bold: '\x1b[1m',
green: '\x1b[32m',
cyan: '\x1b[36m',
yellow: '\x1b[33m',
red: '\x1b[31m',
gray: '\x1b[90m',
white: '\x1b[97m',
};
const CHECK = `${c.green}✓${c.reset}`;
const CROSS = `${c.red}✗${c.reset}`;
const dim = (s) => `${c.gray}${s}${c.reset}`;
import { c, CHECK, CROSS, dim, spinner } from './ui.js';
function findRunning(daemons, profile) {

@@ -58,4 +45,8 @@ return daemons.find(d => d.profile === profile.name || (profile.subdomain && d.subdomain === profile.subdomain));

}
const spin = options.json
? null
: await spinner(`Starting ${profiles.length} profile${profiles.length === 1 ? '' : 's'}…`);
const results = [];
for (const profile of profiles) {
spin?.message(`Starting ${profile.name}…`);
const running = findRunning(cleanupDaemons(), profile);

@@ -115,2 +106,8 @@ if (running) {

else {
const started = results.filter(r => r.status === 'started').length;
const errored = results.filter(r => r.status === 'error').length;
spin?.stop(errored > 0
? `${started} started, ${errored} failed`
: `${started} started${results.length - started > 0 ? ` ${dim(`· ${results.length - started} already running`)}` : ''}`, errored > 0);
console.log('');
for (const r of results) {

@@ -117,0 +114,0 @@ if (r.status === 'error') {

{
"name": "otterkit",
"version": "0.46.0",
"version": "0.47.0",
"description": "OtterKit CLI - provision and connect tunnels for AI agents",

@@ -5,0 +5,0 @@ "mcpName": "io.github.useotterkit/otterkit",

Sorry, the diff of this file is too big to display