@lizard-build/cli 4.0.23 → 4.0.24

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 CHANGED
@@ -63,6 +63,7 @@ lizard ps # list services
63
63
  lizard status # show the linked workspace, project and service
64
64
  lizard logs # stream runtime logs
65
65
  lizard metrics # resource metrics (CPU, memory, network, disk); --cost for spend
66
+ lizard billing # plan, trial, credits used this month; start, cancel or resume Pro
66
67
  lizard metrics --all # all services in the project, even with a linked service
67
68
  lizard scale # scale replicas / CPU / memory / storage
68
69
  lizard secrets # manage secrets
@@ -93,6 +94,19 @@ lizard ssh -s my-app -- printenv
93
94
 
94
95
  Run `lizard --help` for the full list.
95
96
 
97
+ ## Billing
98
+
99
+ ```bash
100
+ lizard billing # plan, trial, credits used this month, next charge
101
+ lizard billing start # start the Pro trial in Stripe Checkout
102
+ lizard billing promo X # redeem a promo code for a longer trial
103
+ ```
104
+
105
+ Pro costs $19/month, taxes included, with $19 in credits each month. Usage
106
+ above that is pay as you go. A new account starts with a 7-day trial with $5 in
107
+ credits. When the account has no plan, commands that create something fail
108
+ with the reason and the link to open next.
109
+
96
110
  ## For agents and scripts
97
111
 
98
112
  Add `--json` to any command for structured output. The CLI also switches to JSON
@@ -0,0 +1,68 @@
1
+ import { Command } from "commander";
2
+ /** Old prepaid credits (`plan: "payg"`) keep working until this date. */
3
+ export declare const CREDITS_END = "November 1, 2026";
4
+ export declare function billingUrl(): string;
5
+ export interface Subscription {
6
+ plan: "none" | "pro" | "payg" | "enterprise" | string;
7
+ status: "none" | "trialing" | "active" | "past_due" | "canceled" | string;
8
+ isOwner?: boolean;
9
+ priceCents: number;
10
+ taxIncluded: boolean;
11
+ includedCents: number;
12
+ trial: {
13
+ eligible: boolean;
14
+ days: number | null;
15
+ creditCents: number | null;
16
+ promoCode: string | null;
17
+ endsAt: number | null;
18
+ usedCents: number | null;
19
+ remainingCents: number | null;
20
+ };
21
+ period: {
22
+ kind: "trial" | "paid";
23
+ start: number;
24
+ end: number;
25
+ includedCents: number;
26
+ usedCents: number;
27
+ overageCents: number;
28
+ billedOverageCents: number;
29
+ unbilledOverageCents: number;
30
+ nextOverageChargeAtCents: number | null;
31
+ } | null;
32
+ nextCharge: {
33
+ at: number | null;
34
+ amountCents: number;
35
+ } | null;
36
+ cancelAt: number | null;
37
+ pastDue: boolean;
38
+ openInvoiceUrl: string | null;
39
+ paymentMethod: {
40
+ brand: string;
41
+ last4: string;
42
+ expMonth: number;
43
+ expYear: number;
44
+ } | null;
45
+ limits: {
46
+ tier: string;
47
+ replicasPerApp: number;
48
+ } | null;
49
+ checkoutAvailable: boolean;
50
+ }
51
+ /** New servers add the trial fields; older ones send only the first four. */
52
+ export interface PromoResult {
53
+ status: string;
54
+ code?: string;
55
+ creditCents: number;
56
+ expiresAt: number | null;
57
+ balanceCents: number;
58
+ trialDays?: number | null;
59
+ trialCreditCents?: number | null;
60
+ appliesTo?: "next_checkout" | "current_trial";
61
+ }
62
+ /** $19, $4.10: whole dollars without cents. */
63
+ export declare function usd(cents: number): string;
64
+ /** Lines that describe a plan, for people. Pure, so the tests can read it. */
65
+ export declare function describeSubscription(sub: Subscription, now?: number): string[];
66
+ /** One line for a redeemed promo code. Works with servers before and after Pro. */
67
+ export declare function describePromo(out: PromoResult): string;
68
+ export declare function registerBilling(program: Command): void;
@@ -0,0 +1,435 @@
1
+ import chalk from "chalk";
2
+ import open from "open";
3
+ import * as p from "@clack/prompts";
4
+ import { api, withQuery, getBaseURL, isNotFound } from "../lib/api.js";
5
+ import { success, isJSONMode, printJSON, table, isTTY, timeAgo, info, warn } from "../lib/format.js";
6
+ // `lizard billing` — the account's plan (docs/pro-billing-api.md on the platform
7
+ // repo). Pro is $19/month, taxes included, with $19 of monthly credits; usage above
8
+ // that is pay as you go. Unlike most commands this never takes --project/--service:
9
+ // billing belongs to the account, not a workspace. `lizard credits` is the old name.
10
+ /** Old prepaid credits (`plan: "payg"`) keep working until this date. */
11
+ export const CREDITS_END = "November 1, 2026";
12
+ const BILLING_PATH = "/profile/account-billing";
13
+ export function billingUrl() {
14
+ return `${getBaseURL()}${BILLING_PATH}`;
15
+ }
16
+ function fmtCents(cents) {
17
+ const sign = cents < 0 ? "-" : "";
18
+ return `${sign}$${(Math.abs(cents) / 100).toFixed(2)}`;
19
+ }
20
+ /** $19, $4.10: whole dollars without cents. */
21
+ export function usd(cents) {
22
+ return cents % 100 === 0 ? `$${cents / 100}` : fmtCents(cents);
23
+ }
24
+ function fmtDate(ms) {
25
+ return new Date(ms).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
26
+ }
27
+ function daysLeft(endMs, now = Date.now()) {
28
+ const days = Math.max(0, Math.ceil((endMs - now) / 86_400_000));
29
+ return days === 1 ? "1 day left" : `${days} days left`;
30
+ }
31
+ function statusLabel(status) {
32
+ switch (status) {
33
+ case "active": return chalk.green(status);
34
+ case "trialing": return chalk.green("trial");
35
+ case "grace":
36
+ case "past_due": return chalk.yellow(status.replace("_", " "));
37
+ case "frozen":
38
+ case "canceled": return chalk.red(status);
39
+ default: return status;
40
+ }
41
+ }
42
+ const creditsNotice = () => `Prepaid credits end on ${CREDITS_END}. Start Pro before then: lizard billing start`;
43
+ /** Lines that describe a plan, for people. Pure, so the tests can read it. */
44
+ export function describeSubscription(sub, now = Date.now()) {
45
+ const lines = [];
46
+ const label = (s) => chalk.dim(s);
47
+ const owner = sub.isOwner === false ? chalk.dim(" (workspace owner's plan)") : "";
48
+ if (sub.plan === "payg") {
49
+ lines.push(`${chalk.bold("Prepaid credits")}${owner}`);
50
+ lines.push(chalk.yellow(creditsNotice()));
51
+ return lines;
52
+ }
53
+ if (sub.plan === "enterprise") {
54
+ lines.push(`${chalk.bold("Enterprise")}${owner}`);
55
+ lines.push("Pay as you go, invoiced monthly.");
56
+ return lines;
57
+ }
58
+ if (sub.plan !== "pro") {
59
+ lines.push(`${chalk.bold("No plan")}${owner}`);
60
+ if (sub.status === "canceled")
61
+ lines.push("Pro has ended.");
62
+ if (sub.isOwner === false) {
63
+ lines.push("The workspace owner has to start Pro.");
64
+ }
65
+ else if (!sub.checkoutAvailable) {
66
+ lines.push("Pro is not open for this account yet.");
67
+ }
68
+ else if (sub.trial.eligible && sub.trial.days) {
69
+ lines.push(`Start a ${sub.trial.days}-day Pro trial with ${usd(sub.trial.creditCents ?? 0)} in credits: ` +
70
+ chalk.cyan("lizard billing start"));
71
+ lines.push(chalk.dim(`No charge today, then ${usd(sub.priceCents)}/month, taxes included.`));
72
+ if (sub.trial.promoCode)
73
+ lines.push(label("Promo code: ") + `${sub.trial.promoCode} (saved for the trial)`);
74
+ }
75
+ else {
76
+ lines.push(`Start Pro: ${usd(sub.priceCents)}/month, taxes included, with ${usd(sub.includedCents)} in credits each month: ` +
77
+ chalk.cyan("lizard billing start"));
78
+ }
79
+ return lines;
80
+ }
81
+ lines.push(`${chalk.bold("Pro")} ${statusLabel(sub.status)}${owner} ` +
82
+ chalk.dim(`${usd(sub.priceCents)}/month, taxes included`));
83
+ const period = sub.period;
84
+ if (sub.status === "trialing") {
85
+ if (sub.trial.endsAt)
86
+ lines.push(label("Trial: ") + `${daysLeft(sub.trial.endsAt, now)}, ends ${fmtDate(sub.trial.endsAt)}`);
87
+ const credit = sub.trial.creditCents ?? period?.includedCents ?? 0;
88
+ const used = sub.trial.usedCents ?? period?.usedCents ?? 0;
89
+ const left = sub.trial.remainingCents ?? Math.max(0, credit - used);
90
+ lines.push(label("Trial credits: ") + `${usd(used)} of ${usd(credit)} used, ${usd(left)} left`);
91
+ }
92
+ else if (period) {
93
+ lines.push(label("This month: ") +
94
+ `${usd(period.usedCents)} of ${usd(period.includedCents)} used` +
95
+ chalk.dim(` (${fmtDate(period.start)} to ${fmtDate(period.end)})`));
96
+ if (period.kind === "paid") {
97
+ let overage = `${usd(period.overageCents)} this month`;
98
+ if (period.overageCents > 0) {
99
+ overage += `, ${usd(period.billedOverageCents)} invoiced so far`;
100
+ if (period.nextOverageChargeAtCents) {
101
+ overage += `; the next invoice goes out at ${usd(period.nextOverageChargeAtCents)}`;
102
+ }
103
+ }
104
+ lines.push(label("Overage: ") + overage);
105
+ }
106
+ }
107
+ if (sub.nextCharge?.at) {
108
+ lines.push(label("Next charge: ") + `${usd(sub.nextCharge.amountCents)} on ${fmtDate(sub.nextCharge.at)}`);
109
+ }
110
+ if (sub.cancelAt) {
111
+ lines.push(chalk.yellow(`Ends on ${fmtDate(sub.cancelAt)}.`) + " Run " + chalk.cyan("lizard billing resume") + " to keep Pro.");
112
+ }
113
+ if (sub.pastDue) {
114
+ lines.push(chalk.red("A payment failed. New resources are blocked until the open invoice is paid."));
115
+ if (sub.openInvoiceUrl)
116
+ lines.push(label("Pay it: ") + chalk.cyan(sub.openInvoiceUrl));
117
+ }
118
+ if (sub.limits) {
119
+ const n = sub.limits.replicasPerApp;
120
+ lines.push(label("Replicas: ") + `up to ${n} per service`);
121
+ }
122
+ if (sub.paymentMethod) {
123
+ const pm = sub.paymentMethod;
124
+ lines.push(label("Card: ") + `${pm.brand} •••• ${pm.last4}` + chalk.dim(` (expires ${pm.expMonth}/${pm.expYear})`));
125
+ }
126
+ return lines;
127
+ }
128
+ async function fetchBalance() {
129
+ return api.get("/api/billing/balance");
130
+ }
131
+ /** The prepaid credits view (old `payg` accounts until November 1, and enterprise usage). */
132
+ function printBalanceView(view) {
133
+ console.log(`${chalk.bold(fmtCents(view.balanceCents))} ${statusLabel(view.status)} ${chalk.dim(`(${view.plan})`)}`);
134
+ if (view.neverFreeze) {
135
+ console.log(chalk.dim("Exempt from billing freeze — balance can go negative with no enforcement."));
136
+ }
137
+ else {
138
+ if (view.overdraftLimitCents != null) {
139
+ console.log(chalk.dim(`Overdraft limit: `) + fmtCents(-view.overdraftLimitCents));
140
+ }
141
+ if (view.availableCents != null) {
142
+ console.log(chalk.dim(`Available before freeze: `) + fmtCents(view.availableCents));
143
+ }
144
+ if (view.graceSince) {
145
+ const deadline = view.graceSince + view.graceHours * 3_600_000;
146
+ const hoursLeft = Math.max(0, Math.round((deadline - Date.now()) / 3_600_000));
147
+ console.log(chalk.yellow(`In grace since ${timeAgo(view.graceSince)} — freezes in ~${hoursLeft}h if unpaid.`));
148
+ }
149
+ }
150
+ if (view.expiringCents > 0 && view.expiringAt) {
151
+ console.log(chalk.dim(`Expiring: `) + `${fmtCents(view.expiringCents)} by ${new Date(view.expiringAt).toLocaleDateString()}`);
152
+ }
153
+ if (view.hourlyRateCents > 0) {
154
+ const rate = chalk.dim(`(~${fmtCents(view.hourlyRateCents)}/hr)`);
155
+ if (view.runwayHours != null) {
156
+ const days = (view.runwayHours / 24).toFixed(1);
157
+ console.log(chalk.dim(`Runway: `) + `~${view.runwayHours}h (${days}d) at current usage ${rate}`);
158
+ }
159
+ else {
160
+ console.log(chalk.dim(`Current usage rate: `) + rate);
161
+ }
162
+ }
163
+ if (view.autoTopup) {
164
+ console.log(chalk.dim("Auto top-up: ") +
165
+ (view.autoTopup.enabled
166
+ ? `on — tops up ${fmtCents(view.autoTopup.amountCents)} when balance drops below ${fmtCents(view.autoTopup.thresholdCents)}`
167
+ : "off"));
168
+ if (view.autoTopup.disabledReason) {
169
+ console.log(chalk.yellow(` disabled: ${view.autoTopup.disabledReason}`));
170
+ }
171
+ }
172
+ if (view.pendingPromo) {
173
+ console.log(chalk.dim("Pending promo: ") + `${view.pendingPromo.code} (${fmtCents(view.pendingPromo.creditCents)})`);
174
+ }
175
+ }
176
+ async function showStatus(opts) {
177
+ let sub;
178
+ try {
179
+ sub = await api.get(withQuery("/api/billing/subscription", { workspaceId: opts.workspace }));
180
+ }
181
+ catch (e) {
182
+ // A server without Pro yet: the prepaid credits view is all there is.
183
+ if (!isNotFound(e) || opts.workspace)
184
+ throw e;
185
+ const view = await fetchBalance();
186
+ if (isJSONMode())
187
+ printJSON(view);
188
+ else
189
+ printBalanceView(view);
190
+ return;
191
+ }
192
+ const url = billingUrl();
193
+ const ownPrepaid = sub.plan === "payg" && sub.isOwner !== false;
194
+ const balance = ownPrepaid ? await fetchBalance() : null;
195
+ if (isJSONMode()) {
196
+ printJSON({
197
+ ...sub,
198
+ billingUrl: url,
199
+ ...(balance ? { balance, notice: `Prepaid credits end on ${CREDITS_END}.` } : {}),
200
+ });
201
+ return;
202
+ }
203
+ if (sub.plan === "payg") {
204
+ if (balance)
205
+ printBalanceView(balance);
206
+ else
207
+ console.log(`${chalk.bold("Prepaid credits")}${chalk.dim(" (workspace owner's plan)")}`);
208
+ console.log(chalk.yellow(creditsNotice()));
209
+ }
210
+ else {
211
+ for (const line of describeSubscription(sub))
212
+ console.log(line);
213
+ }
214
+ console.log(chalk.dim("Billing: ") + chalk.cyan(url));
215
+ }
216
+ async function confirmOrExit(message, yes) {
217
+ if (yes)
218
+ return;
219
+ if (!isTTY())
220
+ throw new Error("Use -y to confirm in non-interactive mode");
221
+ const confirmed = await p.confirm({ message });
222
+ if (p.isCancel(confirmed) || !confirmed)
223
+ process.exit(5);
224
+ }
225
+ async function openInBrowser(url, wanted) {
226
+ if (wanted && isTTY() && !isJSONMode())
227
+ await open(url).catch(() => { });
228
+ }
229
+ /** One line for a redeemed promo code. Works with servers before and after Pro. */
230
+ export function describePromo(out) {
231
+ if (out.trialDays != null) {
232
+ const credits = usd(out.trialCreditCents ?? out.creditCents);
233
+ if (out.appliesTo === "current_trial") {
234
+ const until = out.expiresAt ? `, until ${fmtDate(out.expiresAt)}` : "";
235
+ return `Your trial now runs ${out.trialDays} days with ${credits} in credits${until}.`;
236
+ }
237
+ const code = out.code ? `Code ${out.code} saved: ` : "Code saved: ";
238
+ return `${code}a ${out.trialDays}-day Pro trial with ${credits} in credits. Start it with \`lizard billing start\`.`;
239
+ }
240
+ if (out.status === "pending_payment_method") {
241
+ return `Code saved: ${fmtCents(out.creditCents)} in credits. They unlock when you start your trial in Billing.`;
242
+ }
243
+ return `Redeemed ${fmtCents(out.creditCents)}. New balance: ${fmtCents(out.balanceCents)}.`;
244
+ }
245
+ export function registerBilling(program) {
246
+ const cmd = program
247
+ .command("billing")
248
+ .alias("credits")
249
+ .description("Your plan: Pro trial, this month's credits, next charge, cancel or resume (`credits` is the old name)")
250
+ .option("-w, --workspace <id>", "Show the plan of this workspace's owner")
251
+ .action(async () => {
252
+ await showStatus(cmd.opts());
253
+ });
254
+ cmd.hook("preAction", (thisCommand) => {
255
+ if (thisCommand.parent?.args[0] === "credits") {
256
+ warn("`lizard credits` is now `lizard billing`. The old name will go away in a later release.");
257
+ }
258
+ });
259
+ cmd
260
+ .command("status")
261
+ .description("Show the plan, trial, this month's credits and the next charge")
262
+ .option("-w, --workspace <id>", "Show the plan of this workspace's owner")
263
+ .action(async (opts) => {
264
+ // `billing` takes -w too and claims it wherever it appears on the line.
265
+ await showStatus({ ...cmd.opts(), ...opts });
266
+ });
267
+ cmd
268
+ .command("open")
269
+ .description("Open the Billing page in the browser")
270
+ .option("--no-open", "Print the link instead of opening a browser")
271
+ .action(async (opts) => {
272
+ const url = billingUrl();
273
+ if (isJSONMode()) {
274
+ printJSON({ url, opened: false });
275
+ return;
276
+ }
277
+ console.log(chalk.cyan(url));
278
+ await openInBrowser(url, opts.open !== false);
279
+ });
280
+ cmd
281
+ .command("start")
282
+ .description("Start Pro in Stripe Checkout: the trial if the account can have one, otherwise Pro at once")
283
+ .option("--return-url <path>", "Dashboard path to come back to after Checkout, e.g. /projects/abc")
284
+ .option("--no-open", "Print the Checkout link instead of opening a browser")
285
+ .action(async (opts) => {
286
+ const out = await api.post("/api/billing/subscription/checkout", { returnUrl: opts.returnUrl });
287
+ if (isJSONMode()) {
288
+ printJSON(out);
289
+ return;
290
+ }
291
+ if (out.trialDays) {
292
+ console.log(`Your ${out.trialDays}-day trial includes ${usd(out.trialCreditCents ?? 0)} in credits. ` +
293
+ "No charge today, then $19/month, taxes included.");
294
+ }
295
+ else {
296
+ console.log("Pro starts today: $19/month, taxes included, with $19 in credits each month.");
297
+ }
298
+ console.log(`Finish in Stripe Checkout:\n${chalk.cyan(out.url)}`);
299
+ await openInBrowser(out.url, opts.open !== false);
300
+ info(chalk.dim("Run `lizard billing` when you are done."));
301
+ });
302
+ cmd
303
+ .command("start-now")
304
+ .description("End the trial now: charge $19 and start the first paid month with $19 in credits")
305
+ .option("-y, --yes", "Skip confirmation")
306
+ .option("--no-open", "Print the payment link instead of opening a browser")
307
+ .action(async (opts) => {
308
+ await confirmOrExit("End the trial and charge $19 now?", opts.yes);
309
+ const out = await api.post("/api/billing/subscription/start-now", {});
310
+ if (out.status === "failed") {
311
+ throw Object.assign(new Error(`The charge failed, so your trial continues. Check your card in Billing:\n ${billingUrl()}`), { code: "PAYMENT_FAILED" });
312
+ }
313
+ if (isJSONMode()) {
314
+ printJSON(out);
315
+ return;
316
+ }
317
+ if (out.status === "requires_action" && out.invoiceUrl) {
318
+ console.log(`Your bank needs you to confirm the payment. Your trial continues until you do:\n${chalk.cyan(out.invoiceUrl)}`);
319
+ await openInBrowser(out.invoiceUrl, opts.open !== false);
320
+ return;
321
+ }
322
+ success("Pro is active. We charged $19 and added $19 in credits for this month.");
323
+ });
324
+ cmd
325
+ .command("cancel")
326
+ .description("Cancel Pro at the end of this month or trial; nothing is charged after that")
327
+ .option("-y, --yes", "Skip confirmation")
328
+ .action(async (opts) => {
329
+ await confirmOrExit("Cancel Pro at the end of the current period?", opts.yes);
330
+ const out = await api.post("/api/billing/subscription/cancel", {});
331
+ if (isJSONMode()) {
332
+ printJSON(out);
333
+ return;
334
+ }
335
+ success(out.cancelAt
336
+ ? `Pro ends on ${fmtDate(out.cancelAt)}. Run \`lizard billing resume\` to keep it.`
337
+ : "Pro is cancelled.");
338
+ });
339
+ cmd
340
+ .command("resume")
341
+ .description("Undo a cancel: keep Pro after the current period")
342
+ .action(async () => {
343
+ const out = await api.post("/api/billing/subscription/resume", {});
344
+ if (isJSONMode()) {
345
+ printJSON(out);
346
+ return;
347
+ }
348
+ success("Pro continues. It renews as usual.");
349
+ });
350
+ cmd
351
+ .command("promo <code>")
352
+ .description("Redeem a promo code: a longer Pro trial with more trial credits")
353
+ .action(async (code) => {
354
+ const out = await api.post("/api/billing/promo/redeem", { code });
355
+ if (isJSONMode()) {
356
+ printJSON(out);
357
+ return;
358
+ }
359
+ success(describePromo(out));
360
+ });
361
+ cmd
362
+ .command("balance")
363
+ .description(`Prepaid credits balance (old credits accounts until ${CREDITS_END}, and enterprise)`)
364
+ .action(async () => {
365
+ const view = await fetchBalance();
366
+ if (isJSONMode()) {
367
+ printJSON(view);
368
+ return;
369
+ }
370
+ printBalanceView(view);
371
+ });
372
+ cmd
373
+ .command("transactions")
374
+ .alias("ledger")
375
+ .description("List recent balance transactions (prepaid credits and enterprise accounts)")
376
+ .option("-l, --limit <n>", "Max results (1-100)", "20")
377
+ .option("-c, --cursor <cursor>", "Pagination cursor from a previous call")
378
+ .option("-u, --usage", "Include daily usage-deduction rows")
379
+ .action(async (opts) => {
380
+ const page = await api.get(withQuery("/api/billing/transactions", {
381
+ limit: opts.limit,
382
+ cursor: opts.cursor,
383
+ includeUsage: opts.usage ? "1" : undefined,
384
+ }));
385
+ if (isJSONMode()) {
386
+ printJSON(page);
387
+ return;
388
+ }
389
+ if (page.items.length === 0) {
390
+ console.log("No transactions.");
391
+ return;
392
+ }
393
+ table(["When", "Kind", "Amount", "Balance after", "Description"], page.items.map((t) => [
394
+ timeAgo(t.createdAt),
395
+ t.kind,
396
+ t.amountCents >= 0 ? chalk.green(fmtCents(t.amountCents)) : chalk.red(fmtCents(t.amountCents)),
397
+ t.balanceAfterCents != null ? fmtCents(t.balanceAfterCents) : "—",
398
+ t.description ?? "",
399
+ ]));
400
+ if (page.nextCursor) {
401
+ console.log(chalk.dim(`\nMore results: lizard billing transactions --cursor ${page.nextCursor}`));
402
+ }
403
+ });
404
+ // ── Payment methods ───────────────────────────────────────────────
405
+ const pm = cmd.command("payment-methods").alias("pm").description("List or remove saved cards (add a card in Billing)");
406
+ pm.command("list")
407
+ .description("List saved cards")
408
+ .action(async () => {
409
+ const { items } = await api.get("/api/billing/payment-methods");
410
+ if (isJSONMode()) {
411
+ printJSON(items);
412
+ return;
413
+ }
414
+ if (items.length === 0) {
415
+ console.log(`No saved cards. Add one in Billing: ${chalk.cyan(billingUrl())}`);
416
+ return;
417
+ }
418
+ table(["ID", "Card", "Expires", "Default"], items.map((m) => [m.id, `${m.brand} •••• ${m.last4}`, `${m.expMonth}/${m.expYear}`, m.isDefault ? "yes" : ""]));
419
+ });
420
+ pm.command("remove <id>")
421
+ .alias("rm")
422
+ .description("Remove a saved card")
423
+ .option("-y, --yes", "Skip confirmation")
424
+ .action(async (id, opts) => {
425
+ await confirmOrExit(`Remove payment method ${chalk.bold(id)}?`, opts.yes);
426
+ const out = await api.delete(`/api/billing/payment-methods/${encodeURIComponent(id)}`);
427
+ if (isJSONMode()) {
428
+ printJSON(out);
429
+ }
430
+ else {
431
+ success("Payment method removed");
432
+ }
433
+ });
434
+ }
435
+ //# sourceMappingURL=billing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.js","sourceRoot":"","sources":["../../src/commands/billing.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,15 @@
1
1
  import { Command } from "commander";
2
2
  export declare function registerMetrics(program: Command): void;
3
+ /** This month's Pro credits for the workspace owner's account; null for other plans. */
4
+ interface ProCredits {
5
+ status: string;
6
+ kind: "trial" | "paid";
7
+ periodStart: number;
8
+ periodEnd: number;
9
+ includedCents: number;
10
+ usedCents: number;
11
+ overageCents: number;
12
+ }
13
+ /** "$4.10 of $19 in monthly credits used, overage $0" — the account-wide line for Pro. */
14
+ export declare function proCreditsLine(pro: ProCredits): string;
15
+ export {};
@@ -13,7 +13,7 @@ export function registerMetrics(program) {
13
13
  .option("--all", "Show all services in the project, ignoring the linked service")
14
14
  .option("-r, --range <range>", `Time range: ${RANGES.join("|")}`, "1h")
15
15
  .option("-w, --watch", "Live view, refreshed every 3s (Ctrl+C to stop)")
16
- .option("--cost", "Show running resources, cost per hour, and current billing-period usage (incl. egress)")
16
+ .option("--cost", "Show running resources, cost per hour, current billing-period usage (incl. egress) and Pro credits used this month")
17
17
  .action(async (opts) => {
18
18
  if (opts.all && opts.service) {
19
19
  fail("--all cannot be combined with --service. Choose all services or one service.");
@@ -364,6 +364,31 @@ async function fetchPeriodUsage(projectId, workspaceId) {
364
364
  totalEstimatedUsd: rows.reduce((s, r) => s + r.estimatedUsd, 0),
365
365
  };
366
366
  }
367
+ async function fetchProCredits(workspaceId) {
368
+ const sub = await api
369
+ .get(withQuery("/api/billing/subscription", { workspaceId }))
370
+ .catch(() => null);
371
+ if (!sub || sub.plan !== "pro" || !sub.period)
372
+ return null;
373
+ return {
374
+ status: sub.status,
375
+ kind: sub.period.kind,
376
+ periodStart: sub.period.start,
377
+ periodEnd: sub.period.end,
378
+ includedCents: sub.period.includedCents,
379
+ usedCents: sub.period.usedCents,
380
+ overageCents: sub.period.overageCents,
381
+ };
382
+ }
383
+ const dollars = (cents) => (cents % 100 === 0 ? `$${cents / 100}` : `$${(cents / 100).toFixed(2)}`);
384
+ /** "$4.10 of $19 in monthly credits used, overage $0" — the account-wide line for Pro. */
385
+ export function proCreditsLine(pro) {
386
+ if (pro.kind === "trial") {
387
+ const left = Math.max(0, pro.includedCents - pro.usedCents);
388
+ return `${dollars(pro.usedCents)} of ${dollars(pro.includedCents)} in trial credits used, ${dollars(left)} left`;
389
+ }
390
+ return `${dollars(pro.usedCents)} of ${dollars(pro.includedCents)} in monthly credits used, overage ${dollars(pro.overageCents)}`;
391
+ }
367
392
  function fmtPeriodDate(ms) {
368
393
  return new Date(ms).toLocaleDateString("en-US", { month: "short", day: "numeric" });
369
394
  }
@@ -373,10 +398,12 @@ async function showCost(projectId, scope) {
373
398
  }
374
399
  let data;
375
400
  let usage;
401
+ let pro;
376
402
  try {
377
- [data, usage] = await Promise.all([
403
+ [data, usage, pro] = await Promise.all([
378
404
  api.get(withQuery("/api/billing/live", { workspaceId: scope.workspaceId })),
379
405
  fetchPeriodUsage(projectId, scope.workspaceId),
406
+ fetchProCredits(scope.workspaceId),
380
407
  ]);
381
408
  }
382
409
  catch (e) {
@@ -394,6 +421,8 @@ async function showCost(projectId, scope) {
394
421
  projectCostPerHour: projectCost,
395
422
  workspaceCostPerHour: data.costPerHour,
396
423
  currentPeriod: usage,
424
+ // Pro only: the account's credits this month (the trial's while trialing).
425
+ ...(pro ? { proCredits: pro } : {}),
397
426
  });
398
427
  return;
399
428
  }
@@ -415,6 +444,8 @@ async function showCost(projectId, scope) {
415
444
  chalk.dim(` (~$${(projectCost * 730).toFixed(2)}/mo at current usage)`));
416
445
  }
417
446
  console.log(chalk.dim("Workspace ") + `$${data.costPerHour.toFixed(4)}/hr`);
447
+ if (pro)
448
+ console.log(chalk.dim(pro.kind === "trial" ? "Pro trial " : "Pro ") + proCreditsLine(pro));
418
449
  if (usage && usage.rows.length > 0) {
419
450
  console.log();
420
451
  console.log(chalk.bold("This billing period") +