create-volt 0.43.0 → 0.45.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.
@@ -284,6 +284,21 @@ async function doUpgrade() {
284
284
  status("Upgrade request failed.");
285
285
  }
286
286
  }
287
+
288
+ // AI credits — config-only purchase flow (gateway mode). Hidden unless a
289
+ // VOLT_AI_TOKEN is set and the gateway answers.
290
+ const aiCredits = signal(null); // { ok, tier, creditBalanceUsd, payments } | { ok:false }
291
+ fetch("/setup/ai-credits").then((r) => r.json()).then((c) => aiCredits(c)).catch(() => {});
292
+ async function buyCredits(amountUsd) {
293
+ status("Starting checkout…");
294
+ try {
295
+ const r = await (await fetch("/setup/ai-credits/checkout", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ amountUsd }) })).json();
296
+ if (r.ok && r.url) window.open(r.url, "_blank");
297
+ else status("Checkout failed: " + (r.error || "?"));
298
+ } catch {
299
+ status("Checkout request failed.");
300
+ }
301
+ }
287
302
  const items = signal({ pages: [], posts: [] });
288
303
  const editing = signal(null); // { type, slug, body, isNew } — set only on open/save/close, so typing doesn't re-render
289
304
  const loadItems = async () => items(await (await fetch("/setup/content")).json());
@@ -339,6 +354,7 @@ const manageView = () =>
339
354
 
340
355
  const configView = () =>
341
356
  html`${() => (upgrade()?.available ? html`<div class="card-x p-3 mb-3 d-flex justify-content-between align-items-center"><span class="small">⬆ <strong>create-volt ${upgrade().latest}</strong> is available — you have ${upgrade().current}.</span><button class="btn btn-sm btn-primary" onclick=${doUpgrade}>Upgrade</button></div>` : "")}
357
+ ${() => (aiCredits()?.ok ? html`<div class="card-x p-3 mb-3"><div class="d-flex justify-content-between align-items-center mb-2"><strong>AI credits</strong><span class="small text-muted">${aiCredits().tier}${typeof aiCredits().creditBalanceUsd === "number" ? ` · $${aiCredits().creditBalanceUsd.toFixed(2)} left` : ""}</span></div>${aiCredits().payments ? html`<div class="d-flex gap-2 align-items-center"><span class="small text-muted me-1">Top up:</span>${[10, 25, 50].map((a) => html`<button class="btn btn-sm btn-outline-primary" onclick=${() => buyCredits(a)}>$${a}</button>`)}</div>` : html`<div class="small text-muted">Pay-as-you-go isn't enabled on the gateway yet — using the free tier.</div>`}</div>` : "")}
342
358
  ${available.length ? html`<div class="card-x p-4 mb-3"><h2 class="h6 mb-3">Features</h2>${available.map(addonRow)}<p class="small text-muted mb-0">Enabling a feature wires its backend automatically. Frontend UI (login form, chat) is yours to build — or start from <code>--template guestbook</code>.</p></div>` : ""}
343
359
  <div class="card-x p-4 mb-3">
344
360
  <h2 class="h6 mb-3">Settings</h2>