Skip to content

Commit cf429c9

Browse files
feat(cli): support Polar payments with Convex (#994)
* feat(cli): support polar payments with convex * fix(cli): align convex polar templates with docs * feat(cli): support polar payments in native templates * test(cli): cover native polar server backends * fix(cli): type convex polar auth lookup * fix(cli): sync convex polar products from dashboard * Revert "fix(cli): sync convex polar products from dashboard" This reverts commit 60084d8. * fix(cli): use recurring polar products for subscriptions * fix(cli): keep ui tsconfig browser scoped * fix(cli): align native screens with expo 56 * fix(cli): keep convex polar portal reachable * fix(cli): align bare native home layout * fix(cli): bridge native polar redirects * test(web): cover mixed polar stack builder * fix(cli): address polar review feedback * fix(cli): infer convex polar user type * fix(cli): follow polar user info docs
1 parent e1c6379 commit cf429c9

41 files changed

Lines changed: 2382 additions & 188 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/cli/src/helpers/core/post-installation.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@ export async function displayPostInstallInstructions(
107107
: "";
108108
const clerkInstructions =
109109
config.auth === "clerk" ? getClerkInstructions(frontend || [], backend, api) : "";
110-
const polarInstructions =
111-
config.payments === "polar" && config.auth === "better-auth"
112-
? getPolarInstructions(backend)
113-
: "";
114110
const alchemyDeployInstructions = getAlchemyDeployInstructions(
115111
runCmd,
116112
webDeploy,
@@ -135,6 +131,10 @@ export async function displayPostInstallInstructions(
135131
isConvex && config.auth === "better-auth"
136132
? getBetterAuthConvexInstructions(hasWeb ?? false, webPort, packageManager)
137133
: "";
134+
const polarInstructions =
135+
config.payments === "polar" && config.auth === "better-auth"
136+
? getPolarInstructions(backend, packageManager)
137+
: "";
138138

139139
const bunWebNativeWarning =
140140
packageManager === "bun" && hasNative && hasWeb ? getBunWebNativeWarning() : "";
@@ -572,7 +572,21 @@ function getBetterAuthConvexInstructions(hasWeb: boolean, webPort: string, packa
572572
);
573573
}
574574

575-
function getPolarInstructions(backend: Backend) {
575+
function getPolarInstructions(backend: Backend, packageManager: string) {
576+
if (backend === "convex") {
577+
const cmd = packageManager === "npm" ? "npx" : packageManager;
578+
return (
579+
`${pc.bold("Polar Payments Setup:")}\n` +
580+
`${pc.cyan("•")} Create a Polar organization token, webhook secret, and product in ${pc.underline("https://sandbox.polar.sh/")}\n` +
581+
`${pc.cyan("•")} Set the Convex env vars from ${pc.white("packages/backend")}:\n` +
582+
`${pc.white(" cd packages/backend")}\n` +
583+
`${pc.white(` ${cmd} convex env set POLAR_ORGANIZATION_TOKEN your_polar_token`)}\n` +
584+
`${pc.white(` ${cmd} convex env set POLAR_WEBHOOK_SECRET your_polar_webhook_secret`)}\n` +
585+
`${pc.white(` Optional: ${cmd} convex env set POLAR_SERVER production`)}\n` +
586+
`${pc.cyan("•")} Configure a Polar webhook to ${pc.white("https://<your-convex-site-url>/polar/events")}`
587+
);
588+
}
589+
576590
const envPath = backend === "self" ? "apps/web/.env" : "apps/server/.env";
577591
return `${pc.bold("Polar Payments Setup:")}\n${pc.cyan("•")} Get access token & product ID from ${pc.underline("https://sandbox.polar.sh/")}\n${pc.cyan("•")} Set POLAR_ACCESS_TOKEN in ${envPath}`;
578592
}

apps/cli/src/prompts/payments.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
import { DEFAULT_CONFIG } from "../constants";
22
import type { Auth, Backend, Frontend, Payments } from "../types";
3-
import { splitFrontends } from "../utils/compatibility-rules";
43
import { UserCancelledError } from "../utils/errors";
54
import { isCancel, navigableSelect } from "./navigable";
65

76
export async function getPaymentsChoice(
87
payments?: Payments,
98
auth?: Auth,
109
backend?: Backend,
11-
frontends?: Frontend[],
10+
_frontends?: Frontend[],
1211
) {
1312
if (payments !== undefined) return payments;
1413

1514
if (backend === "none") {
1615
return "none" as Payments;
1716
}
1817

19-
const isPolarCompatible =
20-
auth === "better-auth" &&
21-
backend !== "convex" &&
22-
(frontends?.length === 0 || splitFrontends(frontends).web.length > 0);
18+
const isPolarCompatible = auth === "better-auth";
2319

2420
if (!isPolarCompatible) {
2521
return "none" as Payments;

apps/cli/src/utils/compatibility-rules.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ export function validatePaymentsCompatibility(
400400
payments: Payments | undefined,
401401
auth: Auth | undefined,
402402
_backend: Backend | undefined,
403-
frontends: Frontend[] = [],
403+
_frontends: Frontend[] = [],
404404
): ValidationResult {
405405
if (!payments || payments === "none") return Result.ok(undefined);
406406

@@ -410,13 +410,6 @@ export function validatePaymentsCompatibility(
410410
"Polar payments requires Better Auth. Please use '--auth better-auth' or choose a different payments provider.",
411411
);
412412
}
413-
414-
const { web } = splitFrontends(frontends);
415-
if (web.length === 0 && frontends.length > 0) {
416-
return validationErr(
417-
"Polar payments requires a web frontend or no frontend. Please select a web frontend or choose a different payments provider.",
418-
);
419-
}
420413
}
421414

422415
return Result.ok(undefined);

0 commit comments

Comments
 (0)