Sign In

@decodo/cli

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@decodo/cli - npm Package Compare versions

Comparing version
0.1.3
to
0.1.4
+3
build/esm/auth/errors/config-parse-error.d.ts
export declare class ConfigParseError extends Error {
constructor(configPath: string);
}
export class ConfigParseError extends Error {
constructor(configPath) {
super(`Configuration file is invalid (${configPath}). Run \`decodo setup\` to reconfigure.`);
this.name = "ConfigParseError";
}
}
export declare function promptHidden(message: string): Promise<string>;
import { stdin, stdout } from "node:process";
import { createInterface } from "node:readline/promises";
function handleHiddenPromptChar(char, state) {
if (char === "\u0003") {
state.cleanup();
stdout.write("\n");
state.reject(new Error("Cancelled."));
return;
}
if (char === "\r" || char === "\n") {
state.cleanup();
stdout.write("\n");
state.resolve(state.input.trim());
return;
}
if (char === "\u007f" || char === "\b") {
if (state.input.length > 0) {
state.input = state.input.slice(0, -1);
stdout.write("\b \b");
}
return;
}
state.input += char;
}
export async function promptHidden(message) {
if (!stdin.isTTY) {
const rl = createInterface({ input: stdin, output: stdout });
try {
return (await rl.question(message)).trim();
}
finally {
rl.close();
}
}
stdout.write(message);
return new Promise((resolve, reject) => {
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding("utf8");
const state = {
input: "",
cleanup: () => undefined,
resolve,
reject,
};
const onData = (chunk) => {
for (const char of chunk) {
handleHiddenPromptChar(char, state);
}
};
state.cleanup = () => {
stdin.setRawMode(false);
stdin.pause();
stdin.removeListener("data", onData);
};
stdin.on("data", onData);
});
}
+3
-14

@@ -1,6 +0,5 @@

import { stdin as input, stdout as output } from "node:process";
import { createInterface } from "node:readline/promises";
import { Command } from "commander";
import { getRootOpts } from "../../cli/services/global-opts.js";
import { CliUsageError, handleCliError, } from "../../platform/services/handle-cli-error.js";
import { promptHidden } from "../../platform/services/prompt-hidden.js";
import { validateAuthToken } from "../../scrape/services/auth-validation.js";

@@ -10,12 +9,2 @@ import { PLAYGROUND_URL } from "../constants.js";

const TOKEN_PROMPT = `Paste your Web Scraping API basic auth token (${PLAYGROUND_URL}): `;
async function promptForToken() {
const rl = createInterface({ input, output });
try {
const token = await rl.question(TOKEN_PROMPT);
return token.trim();
}
finally {
rl.close();
}
}
export const setupCommand = new Command("setup")

@@ -26,5 +15,5 @@ .description("Configure the Decodo CLI with your auth token")

const rootOpts = getRootOpts(command);
const token = options.token?.trim() ||
const token = (options.token?.trim() ||
rootOpts.token?.trim() ||
(await promptForToken());
(await promptHidden(TOKEN_PROMPT))).trim();
if (!token) {

@@ -31,0 +20,0 @@ handleCliError(new CliUsageError("auth token is required."));

export declare const PLAYGROUND_URL = "https://dashboard.decodo.com/playground";
export declare const AUTH_MISSING_MESSAGE = "No auth token found. Run `decodo setup` or set DECODO_AUTH_TOKEN.";
export declare const AUTH_MISSING_MESSAGE = "No auth token found.";
export const PLAYGROUND_URL = "https://dashboard.decodo.com/playground";
export const AUTH_MISSING_MESSAGE = "No auth token found. Run `decodo setup` or set DECODO_AUTH_TOKEN.";
export const AUTH_MISSING_MESSAGE = "No auth token found.";
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { getConfigDir } from "../../platform/services/paths.js";
import { ConfigParseError } from "../errors/config-parse-error.js";
const CONFIG_FILE = "config.json";

@@ -8,4 +9,10 @@ export function getConfigPath() {

}
function parseConfig(raw) {
const parsed = JSON.parse(raw);
function parseConfig(raw, configPath) {
let parsed;
try {
parsed = JSON.parse(raw);
}
catch {
throw new ConfigParseError(configPath);
}
if (typeof parsed.authToken === "string" && parsed.authToken.length > 0) {

@@ -22,3 +29,3 @@ return {

const raw = await readFile(configPath, "utf8");
return parseConfig(raw);
return parseConfig(raw, configPath);
}

@@ -25,0 +32,0 @@ catch (err) {

@@ -10,5 +10,4 @@ #!/usr/bin/env node

function readVersion() {
const __filename = fileURLToPath(import.meta.url);
const packageJsonPath = join(dirname(__filename), "..", "..", "package.json");
const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "package.json");
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
return pkg.version;

@@ -15,0 +14,0 @@ }

import { AuthenticationError, DecodoError, RateLimitError, TimeoutError, ValidationError, } from "@decodo/sdk-ts";
import { PLAYGROUND_URL } from "../../auth/constants.js";
import { AuthRequiredError } from "../../auth/errors/auth-required-error.js";

@@ -82,3 +83,9 @@ import { EXIT } from "../constants.js";

}
if (err instanceof AuthRequiredError || err instanceof AuthenticationError) {
if (err instanceof AuthRequiredError) {
console.error("\nThe Decodo CLI is installed and working - it just needs an auth token:\n" +
` 1. Get your Web Scraping API token at ${PLAYGROUND_URL}\n` +
" 2. Run `decodo setup` to save it (or set DECODO_AUTH_TOKEN)\n" +
" 3. Re-run your command");
}
else if (err instanceof AuthenticationError) {
console.error("Hint: Run `decodo setup` to configure your auth token.");

@@ -85,0 +92,0 @@ }

@@ -7,4 +7,4 @@ import { Target as ScrapeTarget } from "@decodo/sdk-ts";

target: ScrapeTarget.Universal,
url: "https://ip.decodo.com",
url: "https://does-not-exist.decodo.com",
});
}
{
"name": "@decodo/cli",
"version": "0.1.3",
"version": "0.1.4",
"description": "Official CLI for the Decodo APIs",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -147,3 +147,3 @@ # Decodo CLI

decodo scrape https://ip.decodo.com
decodo search "top articles hacker news" --limit 5 --parse
decodo google-search "top articles hacker news" --limit 5 --parse
```

@@ -211,3 +211,3 @@

# Search and extract titles
decodo search "rust web scraping" --limit 3 --parse | jq '.[].title'
decodo google-search "rust web scraping" --limit 3 --parse | jq '.[].title'

@@ -226,3 +226,3 @@ # Scrape JSON API endpoint

decodo scrape https://example.com --country us
decodo search "shoes" --geo de --parse
decodo search "shoes" --geo de
decodo google-search "shoes" --geo de --parse

@@ -229,0 +229,0 @@ ```