@kinosec/cli 0.7.1 → 0.8.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/dist/cli.js CHANGED
@@ -6289,6 +6289,7 @@ var KinoSecClient = class {
6289
6289
  reports;
6290
6290
  tokens;
6291
6291
  me;
6292
+ credits;
6292
6293
  audit;
6293
6294
  constructor(config) {
6294
6295
  const prefixPathname = new URL(config.apiUrl).pathname.replace(/\/?$/, "/");
@@ -6338,6 +6339,7 @@ var KinoSecClient = class {
6338
6339
  this.reports = new ReportsResource(this.api);
6339
6340
  this.tokens = new TokensResource(this.api);
6340
6341
  this.me = new MeResource(this.api);
6342
+ this.credits = new CreditsResource(this.api);
6341
6343
  this.audit = new AuditResource(this.api);
6342
6344
  }
6343
6345
  };
@@ -6472,6 +6474,15 @@ var MeResource = class {
6472
6474
  return this.api.get("v1/me").json();
6473
6475
  }
6474
6476
  };
6477
+ var CreditsResource = class {
6478
+ constructor(api) {
6479
+ this.api = api;
6480
+ }
6481
+ api;
6482
+ async get() {
6483
+ return this.api.get("v1/credits").json();
6484
+ }
6485
+ };
6475
6486
  var AuditResource = class {
6476
6487
  constructor(api) {
6477
6488
  this.api = api;
@@ -7353,6 +7364,32 @@ ${content}`);
7353
7364
  // src/lib/errors.ts
7354
7365
  function handleError(error2) {
7355
7366
  if (error2 instanceof ApiError) {
7367
+ if (error2.code === "insufficient_credits") {
7368
+ if (shouldUseJson()) {
7369
+ process.stderr.write(
7370
+ JSON.stringify({
7371
+ error: {
7372
+ status: error2.status,
7373
+ code: error2.code,
7374
+ detail: error2.detail,
7375
+ request_id: error2.requestId
7376
+ }
7377
+ }) + "\n"
7378
+ );
7379
+ } else if (isTTY()) {
7380
+ console.error(import_picocolors2.default.red("\u2717 Insufficient credits"));
7381
+ console.error();
7382
+ console.error(" You don't have enough credits for this scan.");
7383
+ console.error(" Check your balance:");
7384
+ console.error();
7385
+ console.error(` ${import_picocolors2.default.cyan("kinosec credits")}`);
7386
+ console.error();
7387
+ console.error(` Need more? Contact ${import_picocolors2.default.bold("sales@kinosec.com")}`);
7388
+ } else {
7389
+ console.error("Insufficient credits. Check your balance: kinosec credits. Contact sales@kinosec.com");
7390
+ }
7391
+ process.exit(77);
7392
+ }
7356
7393
  if (shouldUseJson()) {
7357
7394
  process.stderr.write(
7358
7395
  JSON.stringify({
@@ -7704,6 +7741,36 @@ Examples:
7704
7741
  });
7705
7742
  }
7706
7743
 
7744
+ // src/commands/credits.ts
7745
+ function registerCreditsCommand(program3) {
7746
+ program3.command("credits").description("Show your credit balance").addHelpText("after", `
7747
+ Examples:
7748
+ $ kinosec credits
7749
+ $ kinosec credits --json`).action(async () => {
7750
+ try {
7751
+ const opts = program3.opts();
7752
+ const { token, apiUrl } = resolveToken(opts);
7753
+ const client = new KinoSecClient({ apiUrl, token });
7754
+ const credits = await client.credits.get();
7755
+ if (opts.json || opts.output === "json") {
7756
+ printJson(credits);
7757
+ return;
7758
+ }
7759
+ const fields = [
7760
+ { label: "Pentest credits", value: String(credits.pentest_credits) },
7761
+ { label: "Quick credits", value: String(credits.quick_pentest_credits) },
7762
+ { label: "Free quick credit", value: String(credits.free_quick_pentest_credits) }
7763
+ ];
7764
+ if (credits.source?.type === "org_pool" && credits.source.org_name) {
7765
+ fields.push({ label: "Source", value: `${credits.source.org_name} org pool` });
7766
+ }
7767
+ printDetail(fields);
7768
+ } catch (error2) {
7769
+ handleError(error2);
7770
+ }
7771
+ });
7772
+ }
7773
+
7707
7774
  // src/commands/pentest.ts
7708
7775
  var import_picocolors6 = __toESM(require_picocolors(), 1);
7709
7776
 
@@ -12572,15 +12639,16 @@ Examples:
12572
12639
 
12573
12640
  // src/cli.ts
12574
12641
  var program2 = new Command();
12575
- program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.7.1", "-v, --version").option("--token <pat>", "API token (overrides KINOSEC_TOKEN)").option("--output <format>", "Output format: text or json", "text").option("--json", "Shorthand for --output json").option("--no-color", "Disable colors");
12642
+ program2.name("kinosec").description("KinoSec CLI \u2014 run pentests from your terminal").version("0.8.0", "-v, --version").option("--token <pat>", "API token (overrides KINOSEC_TOKEN)").option("--output <format>", "Output format: text or json", "text").option("--json", "Shorthand for --output json").option("--no-color", "Disable colors");
12576
12643
  registerAuthCommand(program2);
12577
12644
  registerMeCommand(program2);
12645
+ registerCreditsCommand(program2);
12578
12646
  registerPentestCommand(program2);
12579
12647
  registerAssetCommand(program2);
12580
12648
  registerFindingCommand(program2);
12581
12649
  registerReportCommand(program2);
12582
12650
  registerTokenCommand(program2);
12583
- program2.parseAsync(process.argv).then(() => checkForUpdate("0.7.1")).catch(handleError);
12651
+ program2.parseAsync(process.argv).then(() => checkForUpdate("0.8.0")).catch(handleError);
12584
12652
  /*! Bundled license information:
12585
12653
 
12586
12654
  ky/distribution/index.js: