@blinkdotnew/cli 0.5.0 → 0.5.2

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
@@ -3,6 +3,12 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
7
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
8
+ }) : x)(function(x) {
9
+ if (typeof require !== "undefined") return require.apply(this, arguments);
10
+ throw Error('Dynamic require of "' + x + '" is not supported');
11
+ });
6
12
  var __esm = (fn, res) => function __init() {
7
13
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
14
  };
@@ -2080,7 +2086,8 @@ function getBaseUrl() {
2080
2086
  return process.env.BLINK_APP_URL || "https://blink.new";
2081
2087
  }
2082
2088
  function generateState() {
2083
- return Math.random().toString(36).slice(2) + Date.now().toString(36);
2089
+ const { randomBytes } = __require("crypto");
2090
+ return randomBytes(24).toString("base64url");
2084
2091
  }
2085
2092
  function findFreePort() {
2086
2093
  return new Promise((resolve, reject) => {
@@ -2143,7 +2150,8 @@ async function openBrowserLogin(port, state) {
2143
2150
  const open = await import("open").then((m) => m.default).catch(() => null);
2144
2151
  if (open) await open(url).catch(() => {
2145
2152
  });
2146
- console.log(chalk10.dim(` ${url}
2153
+ else console.log(chalk10.yellow(" Browser did not open automatically."));
2154
+ console.log(chalk10.dim(` If needed, visit: ${url}
2147
2155
  `));
2148
2156
  }
2149
2157
  async function waitForCallback(promise) {
@@ -3655,19 +3663,14 @@ Examples:
3655
3663
 
3656
3664
  // src/commands/billing.ts
3657
3665
  import chalk23 from "chalk";
3658
- function printUsage(data) {
3659
- console.log();
3660
- printKv("Total", `${data.total ?? 0} credits used`);
3661
- const breakdown = data.breakdown ?? [];
3662
- if (breakdown.length) {
3663
- console.log();
3664
- console.log(chalk23.bold("Breakdown:"));
3665
- for (const item of breakdown) printKv(` ${item.category}`, `${item.amount}`);
3666
- }
3667
- console.log();
3666
+ function formatCredits(n) {
3667
+ return n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : n.toFixed(1);
3668
+ }
3669
+ function formatUsd(n) {
3670
+ return `$${n.toFixed(2)}`;
3668
3671
  }
3669
3672
  function registerBillingCommands(program2) {
3670
- program2.command("credits").description("Check your credit balance and tier").addHelpText("after", `
3673
+ program2.command("credits").description("Check your credit usage this month").addHelpText("after", `
3671
3674
  Examples:
3672
3675
  $ blink credits
3673
3676
  $ blink credits --json
@@ -3678,15 +3681,23 @@ Examples:
3678
3681
  () => appRequest("/api/usage/summary?period=month")
3679
3682
  );
3680
3683
  if (isJsonMode()) return printJson(result);
3681
- const data = result ?? {};
3684
+ const buckets = result?.data ?? [];
3685
+ const current = buckets[0];
3682
3686
  console.log();
3683
- printKv("Used", `${data.total ?? 0} credits this month`);
3687
+ if (current) {
3688
+ printKv("Period", current.time_bucket.slice(0, 7));
3689
+ printKv("Credits", formatCredits(current.total_credits));
3690
+ printKv("Requests", String(current.total_requests));
3691
+ printKv("Cost", formatUsd(current.total_cost_usd));
3692
+ } else {
3693
+ console.log(chalk23.dim(" No usage data for this month."));
3694
+ }
3684
3695
  console.log();
3685
3696
  });
3686
- program2.command("usage").description("Show usage summary for the current billing period").option("--period <granularity>", "Period granularity: hour, day, week, month", "day").addHelpText("after", `
3697
+ program2.command("usage").description("Show usage summary for the current billing period").option("--period <granularity>", "Period granularity: hour, day, week, month", "month").addHelpText("after", `
3687
3698
  Examples:
3688
3699
  $ blink usage
3689
- $ blink usage --period month
3700
+ $ blink usage --period day
3690
3701
  $ blink usage --json
3691
3702
  `).action(async (opts) => {
3692
3703
  requireToken();
@@ -3695,7 +3706,16 @@ Examples:
3695
3706
  () => appRequest(`/api/usage/summary?period=${opts.period}`)
3696
3707
  );
3697
3708
  if (isJsonMode()) return printJson(result);
3698
- printUsage(result);
3709
+ const buckets = result?.data ?? [];
3710
+ if (!buckets.length) {
3711
+ console.log(chalk23.dim("\n No usage data.\n"));
3712
+ return;
3713
+ }
3714
+ const table = createTable(["Period", "Credits", "Requests", "Cost"]);
3715
+ for (const b of buckets) {
3716
+ table.push([b.time_bucket.slice(0, 10), formatCredits(b.total_credits), String(b.total_requests), formatUsd(b.total_cost_usd)]);
3717
+ }
3718
+ console.log(table.toString());
3699
3719
  });
3700
3720
  }
3701
3721
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blinkdotnew/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "Blink CLI — full-stack cloud infrastructure from your terminal. Deploy, database, auth, storage, backend, domains, and more.",
5
5
  "bin": {
6
6
  "blink": "dist/cli.js"
@@ -20,7 +20,8 @@ function getBaseUrl(): string {
20
20
  }
21
21
 
22
22
  function generateState(): string {
23
- return Math.random().toString(36).slice(2) + Date.now().toString(36)
23
+ const { randomBytes } = require('node:crypto')
24
+ return randomBytes(24).toString('base64url')
24
25
  }
25
26
 
26
27
  function findFreePort(): Promise<number> {
@@ -89,7 +90,8 @@ async function openBrowserLogin(port: number, state: string) {
89
90
  const url = `${getBaseUrl()}/auth/cli?port=${port}&state=${state}`
90
91
  const open = await import('open').then(m => m.default).catch(() => null)
91
92
  if (open) await open(url).catch(() => {})
92
- console.log(chalk.dim(` ${url}\n`))
93
+ else console.log(chalk.yellow(' Browser did not open automatically.'))
94
+ console.log(chalk.dim(` If needed, visit: ${url}\n`))
93
95
  }
94
96
 
95
97
  async function waitForCallback(
@@ -1,24 +1,28 @@
1
1
  import { Command } from 'commander'
2
2
  import { appRequest } from '../lib/api-app.js'
3
3
  import { requireToken } from '../lib/auth.js'
4
- import { printJson, printKv, isJsonMode, withSpinner } from '../lib/output.js'
4
+ import { printJson, printKv, isJsonMode, withSpinner, createTable } from '../lib/output.js'
5
5
  import chalk from 'chalk'
6
6
 
7
- function printUsage(data: { total?: number; breakdown?: Array<{ category: string; amount: number }> }) {
8
- console.log()
9
- printKv('Total', `${data.total ?? 0} credits used`)
10
- const breakdown = data.breakdown ?? []
11
- if (breakdown.length) {
12
- console.log()
13
- console.log(chalk.bold('Breakdown:'))
14
- for (const item of breakdown) printKv(` ${item.category}`, `${item.amount}`)
15
- }
16
- console.log()
7
+ interface UsageBucket {
8
+ period: string
9
+ time_bucket: string
10
+ total_credits: number
11
+ total_requests: number
12
+ total_cost_usd: number
13
+ }
14
+
15
+ function formatCredits(n: number): string {
16
+ return n >= 1000 ? `${(n / 1000).toFixed(1)}k` : n.toFixed(1)
17
+ }
18
+
19
+ function formatUsd(n: number): string {
20
+ return `$${n.toFixed(2)}`
17
21
  }
18
22
 
19
23
  export function registerBillingCommands(program: Command) {
20
24
  program.command('credits')
21
- .description('Check your credit balance and tier')
25
+ .description('Check your credit usage this month')
22
26
  .addHelpText('after', `
23
27
  Examples:
24
28
  $ blink credits
@@ -30,19 +34,27 @@ Examples:
30
34
  appRequest('/api/usage/summary?period=month')
31
35
  )
32
36
  if (isJsonMode()) return printJson(result)
33
- const data = result ?? {}
37
+ const buckets: UsageBucket[] = result?.data ?? []
38
+ const current = buckets[0]
34
39
  console.log()
35
- printKv('Used', `${data.total ?? 0} credits this month`)
40
+ if (current) {
41
+ printKv('Period', current.time_bucket.slice(0, 7))
42
+ printKv('Credits', formatCredits(current.total_credits))
43
+ printKv('Requests', String(current.total_requests))
44
+ printKv('Cost', formatUsd(current.total_cost_usd))
45
+ } else {
46
+ console.log(chalk.dim(' No usage data for this month.'))
47
+ }
36
48
  console.log()
37
49
  })
38
50
 
39
51
  program.command('usage')
40
52
  .description('Show usage summary for the current billing period')
41
- .option('--period <granularity>', 'Period granularity: hour, day, week, month', 'day')
53
+ .option('--period <granularity>', 'Period granularity: hour, day, week, month', 'month')
42
54
  .addHelpText('after', `
43
55
  Examples:
44
56
  $ blink usage
45
- $ blink usage --period month
57
+ $ blink usage --period day
46
58
  $ blink usage --json
47
59
  `)
48
60
  .action(async (opts) => {
@@ -51,6 +63,15 @@ Examples:
51
63
  appRequest(`/api/usage/summary?period=${opts.period}`)
52
64
  )
53
65
  if (isJsonMode()) return printJson(result)
54
- printUsage(result)
66
+ const buckets: UsageBucket[] = result?.data ?? []
67
+ if (!buckets.length) {
68
+ console.log(chalk.dim('\n No usage data.\n'))
69
+ return
70
+ }
71
+ const table = createTable(['Period', 'Credits', 'Requests', 'Cost'])
72
+ for (const b of buckets) {
73
+ table.push([b.time_bucket.slice(0, 10), formatCredits(b.total_credits), String(b.total_requests), formatUsd(b.total_cost_usd)])
74
+ }
75
+ console.log(table.toString())
55
76
  })
56
77
  }