paddle-checkout-accelerator 2.4.0 → 2.5.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.
|
@@ -17,6 +17,9 @@ const interactive =
|
|
|
17
17
|
args.has("--interactive") ||
|
|
18
18
|
args.has("-i");
|
|
19
19
|
|
|
20
|
+
const minimal =
|
|
21
|
+
args.has("--minimal");
|
|
22
|
+
|
|
20
23
|
function exists(filePath) {
|
|
21
24
|
return fs.existsSync(
|
|
22
25
|
path.join(cwd, filePath)
|
|
@@ -126,6 +129,7 @@ async function getConfig() {
|
|
|
126
129
|
env: true,
|
|
127
130
|
schema:
|
|
128
131
|
detectedAdapter === "prisma",
|
|
132
|
+
ui: !minimal,
|
|
129
133
|
};
|
|
130
134
|
}
|
|
131
135
|
|
|
@@ -180,6 +184,15 @@ async function getConfig() {
|
|
|
180
184
|
active: "yes",
|
|
181
185
|
inactive: "no",
|
|
182
186
|
},
|
|
187
|
+
{
|
|
188
|
+
type: "toggle",
|
|
189
|
+
name: "ui",
|
|
190
|
+
message:
|
|
191
|
+
"Generate billing UI pages?",
|
|
192
|
+
initial: true,
|
|
193
|
+
active: "yes",
|
|
194
|
+
inactive: "no",
|
|
195
|
+
},
|
|
183
196
|
]);
|
|
184
197
|
|
|
185
198
|
if (!answers.adapter) {
|
|
@@ -289,6 +302,198 @@ model BillingEvent {
|
|
|
289
302
|
);
|
|
290
303
|
}
|
|
291
304
|
|
|
305
|
+
function writeUiPages() {
|
|
306
|
+
writeFileSafe(
|
|
307
|
+
"src/app/billing/pricing/page.tsx",
|
|
308
|
+
`import {
|
|
309
|
+
PricingTable,
|
|
310
|
+
} from "paddle-checkout-accelerator";
|
|
311
|
+
|
|
312
|
+
export default function BillingPricingPage() {
|
|
313
|
+
return (
|
|
314
|
+
<main className="mx-auto max-w-5xl p-10">
|
|
315
|
+
<h1 className="text-4xl font-bold">
|
|
316
|
+
Choose your plan
|
|
317
|
+
</h1>
|
|
318
|
+
|
|
319
|
+
<p className="mt-3 text-gray-500">
|
|
320
|
+
Upgrade your account with Paddle billing.
|
|
321
|
+
</p>
|
|
322
|
+
|
|
323
|
+
<div className="mt-8">
|
|
324
|
+
<PricingTable />
|
|
325
|
+
</div>
|
|
326
|
+
</main>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
`
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
writeFileSafe(
|
|
333
|
+
"src/app/billing/dashboard/page.tsx",
|
|
334
|
+
`import {
|
|
335
|
+
BillingHistory,
|
|
336
|
+
CustomerPortalButton,
|
|
337
|
+
SubscriptionCard,
|
|
338
|
+
TrialBanner,
|
|
339
|
+
UsageMeter,
|
|
340
|
+
} from "paddle-checkout-accelerator";
|
|
341
|
+
|
|
342
|
+
export default function BillingDashboardPage() {
|
|
343
|
+
return (
|
|
344
|
+
<main className="mx-auto max-w-5xl space-y-6 p-10">
|
|
345
|
+
<TrialBanner daysRemaining={5} />
|
|
346
|
+
|
|
347
|
+
<SubscriptionCard
|
|
348
|
+
plan="Pro"
|
|
349
|
+
status="Active"
|
|
350
|
+
/>
|
|
351
|
+
|
|
352
|
+
<UsageMeter
|
|
353
|
+
current={37}
|
|
354
|
+
limit={50}
|
|
355
|
+
/>
|
|
356
|
+
|
|
357
|
+
<CustomerPortalButton />
|
|
358
|
+
|
|
359
|
+
<BillingHistory />
|
|
360
|
+
</main>
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
`
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
writeFileSafe(
|
|
367
|
+
"src/app/billing/customer-repair/page.tsx",
|
|
368
|
+
`"use client";
|
|
369
|
+
|
|
370
|
+
import { useState } from "react";
|
|
371
|
+
|
|
372
|
+
export default function CustomerRepairPage() {
|
|
373
|
+
const [email, setEmail] =
|
|
374
|
+
useState("");
|
|
375
|
+
const [result, setResult] =
|
|
376
|
+
useState("");
|
|
377
|
+
|
|
378
|
+
async function repair() {
|
|
379
|
+
const response =
|
|
380
|
+
await fetch(
|
|
381
|
+
"/api/paddle/repair-by-email",
|
|
382
|
+
{
|
|
383
|
+
method: "POST",
|
|
384
|
+
headers: {
|
|
385
|
+
"Content-Type":
|
|
386
|
+
"application/json",
|
|
387
|
+
},
|
|
388
|
+
body: JSON.stringify({
|
|
389
|
+
email,
|
|
390
|
+
}),
|
|
391
|
+
}
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
const data =
|
|
395
|
+
await response.json();
|
|
396
|
+
|
|
397
|
+
setResult(
|
|
398
|
+
JSON.stringify(data, null, 2)
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<main className="mx-auto max-w-3xl space-y-6 p-10">
|
|
404
|
+
<div>
|
|
405
|
+
<h1 className="text-4xl font-bold">
|
|
406
|
+
Repair Customer Access
|
|
407
|
+
</h1>
|
|
408
|
+
|
|
409
|
+
<p className="mt-3 text-gray-500">
|
|
410
|
+
Use this when a customer paid but their account did not unlock.
|
|
411
|
+
</p>
|
|
412
|
+
</div>
|
|
413
|
+
|
|
414
|
+
<input
|
|
415
|
+
value={email}
|
|
416
|
+
onChange={(event) =>
|
|
417
|
+
setEmail(event.target.value)
|
|
418
|
+
}
|
|
419
|
+
placeholder="customer@example.com"
|
|
420
|
+
className="w-full rounded-xl border p-4"
|
|
421
|
+
/>
|
|
422
|
+
|
|
423
|
+
<button
|
|
424
|
+
onClick={repair}
|
|
425
|
+
className="rounded-xl bg-black px-6 py-3 text-white"
|
|
426
|
+
>
|
|
427
|
+
Repair Subscription
|
|
428
|
+
</button>
|
|
429
|
+
|
|
430
|
+
{result && (
|
|
431
|
+
<pre className="overflow-auto rounded-xl border bg-slate-50 p-5 text-sm">
|
|
432
|
+
{result}
|
|
433
|
+
</pre>
|
|
434
|
+
)}
|
|
435
|
+
</main>
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
`
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
writeFileSafe(
|
|
442
|
+
"src/app/billing/protected-api/page.tsx",
|
|
443
|
+
`"use client";
|
|
444
|
+
|
|
445
|
+
import { useState } from "react";
|
|
446
|
+
|
|
447
|
+
export default function ProtectedApiPage() {
|
|
448
|
+
const [result, setResult] =
|
|
449
|
+
useState("");
|
|
450
|
+
|
|
451
|
+
async function run() {
|
|
452
|
+
const response =
|
|
453
|
+
await fetch(
|
|
454
|
+
"/api/demo/protected-generation",
|
|
455
|
+
{
|
|
456
|
+
method: "POST",
|
|
457
|
+
}
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
const data =
|
|
461
|
+
await response.json();
|
|
462
|
+
|
|
463
|
+
setResult(
|
|
464
|
+
JSON.stringify(data, null, 2)
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return (
|
|
469
|
+
<main className="mx-auto max-w-3xl space-y-6 p-10">
|
|
470
|
+
<h1 className="text-4xl font-bold">
|
|
471
|
+
Protected API Demo
|
|
472
|
+
</h1>
|
|
473
|
+
|
|
474
|
+
<p className="text-gray-500">
|
|
475
|
+
Test paid-route protection, feature checks, and usage limits.
|
|
476
|
+
</p>
|
|
477
|
+
|
|
478
|
+
<button
|
|
479
|
+
onClick={run}
|
|
480
|
+
className="rounded-xl bg-black px-6 py-3 text-white"
|
|
481
|
+
>
|
|
482
|
+
Run Protected Action
|
|
483
|
+
</button>
|
|
484
|
+
|
|
485
|
+
{result && (
|
|
486
|
+
<pre className="overflow-auto rounded-xl border bg-slate-50 p-5 text-sm">
|
|
487
|
+
{result}
|
|
488
|
+
</pre>
|
|
489
|
+
)}
|
|
490
|
+
</main>
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
`
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
292
497
|
function writeRoutes() {
|
|
293
498
|
writeFileSafe(
|
|
294
499
|
"src/app/api/paddle/webhook/route.ts",
|
|
@@ -442,6 +647,7 @@ Usage:
|
|
|
442
647
|
npx paddle-checkout-accelerator init
|
|
443
648
|
npx paddle-checkout-accelerator init --interactive
|
|
444
649
|
npx paddle-checkout-accelerator init --force
|
|
650
|
+
npx paddle-checkout-accelerator init --minimal
|
|
445
651
|
`);
|
|
446
652
|
process.exit(0);
|
|
447
653
|
}
|
|
@@ -472,6 +678,10 @@ Usage:
|
|
|
472
678
|
writeRoutes();
|
|
473
679
|
}
|
|
474
680
|
|
|
681
|
+
if (config.ui) {
|
|
682
|
+
writeUiPages();
|
|
683
|
+
}
|
|
684
|
+
|
|
475
685
|
if (config.env) {
|
|
476
686
|
appendEnvSafe({
|
|
477
687
|
NEXT_PUBLIC_PADDLE_CLIENT_TOKEN: "",
|