Skip to content

Commit 0f1ca22

Browse files
committed
add customer state support
1 parent 4e391f3 commit 0f1ca22

File tree

59 files changed

+1269
-1955
lines changed

Some content is hidden

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

59 files changed

+1269
-1955
lines changed

.changeset/rare-jars-exist.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@polar-sh/better-auth": patch
3+
"@polar-sh/sveltekit": patch
4+
"@polar-sh/adapter-utils": patch
5+
"@polar-sh/express": patch
6+
"@polar-sh/fastify": patch
7+
"@polar-sh/elysia": patch
8+
"@polar-sh/nextjs": patch
9+
"@polar-sh/astro": patch
10+
"@polar-sh/remix": patch
11+
"@polar-sh/hono": patch
12+
"@polar-sh/nuxt": patch
13+
---
14+
15+
Add customer state support

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ This repository hosts a wide array of Polar adapters for your TypeScript framewo
1313
- [Next.js](./packages/polar-nextjs)
1414
- [Nuxt](./packages/polar-nuxt)
1515
- [Remix](./packages/polar-remix)
16-
- [Sveltekit](./packages/polar-sveltekit)
16+
- [Sveltekit](./packages/polar-sveltekit)

packages/adapter-utils/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"author": "",
2525
"license": "Apache-2.0",
2626
"dependencies": {
27-
"@polar-sh/sdk": "^0.24.0"
27+
"@polar-sh/sdk": "^0.29.2"
2828
},
2929
"devDependencies": {
3030
"@sindresorhus/tsconfig": "^7.0.0",

packages/adapter-utils/src/webhooks/webhooks.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { validateEvent } from "@polar-sh/sdk/webhooks";
1+
import type { validateEvent } from "@polar-sh/sdk/webhooks";
22
import type { WebhookBenefitCreatedPayload } from "@polar-sh/sdk/models/components/webhookbenefitcreatedpayload";
33
import type { WebhookBenefitGrantCreatedPayload } from "@polar-sh/sdk/models/components/webhookbenefitgrantcreatedpayload";
44
import type { WebhookBenefitGrantRevokedPayload } from "@polar-sh/sdk/models/components/webhookbenefitgrantrevokedpayload";
@@ -19,7 +19,11 @@ import type { WebhookSubscriptionCreatedPayload } from "@polar-sh/sdk/models/com
1919
import type { WebhookSubscriptionRevokedPayload } from "@polar-sh/sdk/models/components/webhooksubscriptionrevokedpayload";
2020
import type { WebhookSubscriptionUncanceledPayload } from "@polar-sh/sdk/models/components/webhooksubscriptionuncanceledpayload";
2121
import type { WebhookSubscriptionUpdatedPayload } from "@polar-sh/sdk/models/components/webhooksubscriptionupdatedpayload";
22-
import { Entitlements } from "../entitlement/entitlement";
22+
import type { Entitlements } from "../entitlement/entitlement";
23+
import type { WebhookCustomerUpdatedPayload } from "@polar-sh/sdk/models/components/webhookcustomerupdatedpayload.js";
24+
import type { WebhookCustomerDeletedPayload } from "@polar-sh/sdk/models/components/webhookcustomerdeletedpayload.js";
25+
import type { WebhookCustomerCreatedPayload } from "@polar-sh/sdk/models/components/webhookcustomercreatedpayload.js";
26+
import type { WebhookCustomerStateChangedPayload } from "@polar-sh/sdk/models/components/webhookcustomerstatechangedpayload.js";
2327

2428
export interface WebhooksConfig {
2529
webhookSecret: string;
@@ -65,6 +69,12 @@ export interface WebhooksConfig {
6569
onBenefitGrantRevoked?: (
6670
payload: WebhookBenefitGrantRevokedPayload,
6771
) => Promise<void>;
72+
onCustomerCreated?: (payload: WebhookCustomerCreatedPayload) => Promise<void>;
73+
onCustomerUpdated?: (payload: WebhookCustomerUpdatedPayload) => Promise<void>;
74+
onCustomerDeleted?: (payload: WebhookCustomerDeletedPayload) => Promise<void>;
75+
onCustomerStateChanged?: (
76+
payload: WebhookCustomerStateChangedPayload,
77+
) => Promise<void>;
6878
}
6979

7080
export const handleWebhookPayload = async (
@@ -157,6 +167,27 @@ export const handleWebhookPayload = async (
157167
if (eventHandlers.onBenefitGrantRevoked) {
158168
promises.push(eventHandlers.onBenefitGrantRevoked(payload));
159169
}
170+
break;
171+
case "customer.created":
172+
if (eventHandlers.onCustomerCreated) {
173+
promises.push(eventHandlers.onCustomerCreated(payload));
174+
}
175+
break;
176+
case "customer.updated":
177+
if (eventHandlers.onCustomerUpdated) {
178+
promises.push(eventHandlers.onCustomerUpdated(payload));
179+
}
180+
break;
181+
case "customer.deleted":
182+
if (eventHandlers.onCustomerDeleted) {
183+
promises.push(eventHandlers.onCustomerDeleted(payload));
184+
}
185+
break;
186+
case "customer.state_changed":
187+
if (eventHandlers.onCustomerStateChanged) {
188+
promises.push(eventHandlers.onCustomerStateChanged(payload));
189+
}
190+
break;
160191
}
161192

162193
switch (payload.type) {

packages/polar-astro/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Pass query params to this route.
2626
- productId (or productPriceId) `?productId=xxx`
2727
- productPriceId (or productId) `?productPriceId=xxx`
2828
- customerId (optional) `?productId=xxx&customerId=xxx`
29+
- customerExternalId (optional) `?productdId=xxx&customerExternalId=xxx`
2930
- customerEmail (optional) `?productId=xxx&customerEmail=janedoe@gmail.com`
3031
- customerName (optional) `?productId=xxx&customerName=Jane`
3132
- metadata (optional) `URL-Encoded JSON string`
@@ -79,3 +80,7 @@ The Webhook handler also supports granular handlers for easy integration.
7980
- onBenefitGrantCreated: (payload) =>
8081
- onBenefitGrantUpdated: (payload) =>
8182
- onBenefitGrantRevoked: (payload) =>
83+
- onCustomerCreated: (payload) =>
84+
- onCustomerUpdated: (payload) =>
85+
- onCustomerDeleted: (payload) =>
86+
- onCustomerStateChanged: (payload) =>

packages/polar-astro/package.json

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,45 @@
11
{
2-
"name": "@polar-sh/astro",
3-
"version": "0.3.12",
4-
"description": "Polar integration for Astro",
5-
"main": "./dist/index.cjs",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"import": {
10-
"types": "./dist/index.d.ts",
11-
"import": "./dist/index.js"
12-
},
13-
"require": {
14-
"types": "./dist/index.d.cts",
15-
"require": "./dist/index.cjs"
16-
}
17-
},
18-
"type": "module",
19-
"engines": {
20-
"node": ">=16"
21-
},
22-
"scripts": {
23-
"test": "vitest",
24-
"build": "tsup ./src/index.ts --format esm,cjs --dts --clean --sourcemap --external 'astro:env/server'",
25-
"dev": "tsc --watch",
26-
"check": "biome check --write ./src"
27-
},
28-
"files": [
29-
"dist"
30-
],
31-
"keywords": [
32-
"polar",
33-
"withastro",
34-
"payments",
35-
"subscriptions"
36-
],
37-
"peerDependencies": {
38-
"astro": "^5.0.0"
39-
},
40-
"devDependencies": {
41-
"@biomejs/biome": "1.9.4",
42-
"@sindresorhus/tsconfig": "^7.0.0",
43-
"@types/node": "^20.0.0",
44-
"prettier": "^3.2.5",
45-
"tsup": "^8.3.5",
46-
"vitest": "^2.1.8"
47-
},
48-
"dependencies": {
49-
"@polar-sh/adapter-utils": "workspace:*",
50-
"@polar-sh/sdk": "^0.24.0"
51-
}
2+
"name": "@polar-sh/astro",
3+
"version": "0.3.12",
4+
"description": "Polar integration for Astro",
5+
"main": "./dist/index.cjs",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"import": {
10+
"types": "./dist/index.d.ts",
11+
"import": "./dist/index.js"
12+
},
13+
"require": {
14+
"types": "./dist/index.d.cts",
15+
"require": "./dist/index.cjs"
16+
}
17+
},
18+
"type": "module",
19+
"engines": {
20+
"node": ">=16"
21+
},
22+
"scripts": {
23+
"test": "vitest",
24+
"build": "tsup ./src/index.ts --format esm,cjs --dts --clean --sourcemap --external 'astro:env/server'",
25+
"dev": "tsc --watch",
26+
"check": "biome check --write ./src"
27+
},
28+
"files": ["dist"],
29+
"keywords": ["polar", "withastro", "payments", "subscriptions"],
30+
"peerDependencies": {
31+
"astro": "^5.0.0"
32+
},
33+
"devDependencies": {
34+
"@biomejs/biome": "1.9.4",
35+
"@sindresorhus/tsconfig": "^7.0.0",
36+
"@types/node": "^20.0.0",
37+
"prettier": "^3.2.5",
38+
"tsup": "^8.3.5",
39+
"vitest": "^2.1.8"
40+
},
41+
"dependencies": {
42+
"@polar-sh/adapter-utils": "workspace:*",
43+
"@polar-sh/sdk": "^0.29.2"
44+
}
5245
}

packages/polar-astro/src/checkout/checkout.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export const Checkout = ({
4848
: { productPriceId: productPriceId ?? "" }),
4949
successUrl: success ? decodeURI(success.toString()) : undefined,
5050
customerId: url.searchParams.get("customerId") ?? undefined,
51+
customerExternalId:
52+
url.searchParams.get("customerExternalId") ?? undefined,
5153
customerEmail: url.searchParams.get("customerEmail") ?? undefined,
5254
customerName: url.searchParams.get("customerName") ?? undefined,
5355
customerBillingAddress: url.searchParams.has("customerBillingAddress")

packages/polar-betterauth/README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ import { Polar } from "@polar-sh/sdk";
3131

3232
const client = new Polar({
3333
accessToken: process.env.POLAR_ACCESS_TOKEN,
34-
// Use 'sandbox' if you're using the Polar Sandbox environment
35-
// Remember that access tokens, products, etc. are completely separated between environments.
34+
// Use 'sandbox' if you're using the Polar Sandbox environment
35+
// Remember that access tokens, products, etc. are completely separated between environments.
3636
// Access tokens obtained in Production are for instance not usable in the Sandbox environment.
37-
server: 'production'
37+
server: 'production'
3838
});
3939

4040
const auth = betterAuth({
@@ -130,7 +130,6 @@ The plugin adds the following API routes:
130130
- `GET /customer-portal` - Redirects to Polar Customer Portal for authenticated user
131131
- `POST /polar/webhooks` - Incoming webhooks are automatically parsed & validated
132132

133-
134133
## Customers
135134

136135
When `createCustomerOnSignUp` is enabled, a new Polar Customer is automatically created when a new User is added in the Better-Auth Database.
@@ -139,7 +138,7 @@ All new customers are created with an associated `externalId`, which is the ID o
139138

140139
## Checkouts
141140

142-
When checkouts are enabled, you're able to initialize Checkout Sessions on the `/checkout/:slug` route.
141+
When checkouts are enabled, you're able to initialize Checkout Sessions on the `/checkout/:slug` route.
143142

144143
### Checkouts with slug
145144

@@ -149,4 +148,4 @@ If you pass an array of products to the configuration, you're able to use the sl
149148

150149
All your organization products are eligible for checkouts, even if they're not passed to the products-configuration.
151150

152-
You can initialize a checkout session like following - `/checkout?productId=123-456-789`
151+
You can initialize a checkout session like following - `/checkout?productId=123-456-789`

packages/polar-betterauth/example/src/app/page.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { Me } from "@/components/Me";
33
import { Register } from "@/components/Register";
44

55
export default function Home() {
6-
return (
7-
<div className="flex flex-row gap-4 items-center justify-center h-screen">
8-
<Me />
9-
<Register />
10-
<Login />
11-
</div>
12-
);
6+
return (
7+
<div className="flex flex-row gap-4 items-center justify-center h-screen">
8+
<Me />
9+
<Register />
10+
<Login />
11+
</div>
12+
);
1313
}

packages/polar-betterauth/example/src/components/Login.tsx

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,38 @@ import { signIn } from "@/lib/auth-client";
44
import { useState } from "react";
55

66
export const Login = () => {
7-
const [email, setEmail] = useState("");
8-
const [password, setPassword] = useState("");
7+
const [email, setEmail] = useState("");
8+
const [password, setPassword] = useState("");
99

10-
return (
11-
<div className="flex flex-col gap-4">
12-
<h1>Login</h1>
13-
<input
14-
type="email"
15-
placeholder="Email"
16-
value={email}
17-
onChange={(e) => setEmail(e.target.value)}
18-
/>
19-
<input
20-
type="password"
21-
placeholder="Password"
22-
value={password}
23-
onChange={(e) => setPassword(e.target.value)}
24-
/>
25-
<button
26-
type="button"
27-
className="bg-blue-500 text-white p-2 rounded-md"
28-
onClick={async () => {
29-
const user = await signIn.email({
30-
email,
31-
password,
32-
});
10+
return (
11+
<div className="flex flex-col gap-4">
12+
<h1>Login</h1>
13+
<input
14+
type="email"
15+
placeholder="Email"
16+
value={email}
17+
onChange={(e) => setEmail(e.target.value)}
18+
/>
19+
<input
20+
type="password"
21+
placeholder="Password"
22+
value={password}
23+
onChange={(e) => setPassword(e.target.value)}
24+
/>
25+
<button
26+
type="button"
27+
className="bg-blue-500 text-white p-2 rounded-md"
28+
onClick={async () => {
29+
const user = await signIn.email({
30+
email,
31+
password,
32+
});
3333

34-
console.log(user);
35-
}}
36-
>
37-
Sign In
38-
</button>
39-
</div>
40-
);
34+
console.log(user);
35+
}}
36+
>
37+
Sign In
38+
</button>
39+
</div>
40+
);
4141
};

packages/polar-betterauth/example/src/components/Me.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import { useSession } from "@/lib/auth-client";
44

55
export const Me = () => {
6-
const { data: session } = useSession();
6+
const { data: session } = useSession();
77

8-
if (!session) {
9-
return <div>Not authenticated</div>;
10-
}
8+
if (!session) {
9+
return <div>Not authenticated</div>;
10+
}
1111

12-
return (
13-
<div>
14-
<h1>Welcome {session.user.name}</h1>
15-
</div>
16-
);
12+
return (
13+
<div>
14+
<h1>Welcome {session.user.name}</h1>
15+
</div>
16+
);
1717
};

0 commit comments

Comments
 (0)