feat: sync autumn customer after signup

This commit is contained in:
2026-07-02 04:11:31 -07:00
parent c0c22513c9
commit efc2110f44
2 changed files with 63 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
import { betterAuth } from "better-auth";
import { syncAutumnCustomerOnRegistration } from "./autumn";
import { buildAuthEmail, sendEmail } from "./email";
import { trustedOrigins, type Env } from "./env";
import { createSocialProviders } from "./oauth";
@@ -19,6 +20,21 @@ export function createAuth(env: Env, runtime: AuthRuntime = {}) {
secret: env.BETTER_AUTH_SECRET ?? "development-secret-change-before-production",
baseURL: env.BETTER_AUTH_URL,
trustedOrigins: trustedOrigins(env, runtime.requestOrigin),
databaseHooks: {
user: {
create: {
after: async (user) => {
const sync = syncAutumnCustomerOnRegistration(env, user);
if (runtime.waitUntil) {
runtime.waitUntil(sync);
return;
}
await sync;
},
},
},
},
session: {
cookieCache: {
enabled: true,

View File

@@ -1,5 +1,5 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { createAuth } from "../src/auth";
import {
booleanEnv,
@@ -89,6 +89,52 @@ describe("auth env helpers", () => {
});
});
describe("Autumn registration hook", () => {
it("schedules Autumn sync after Better Auth creates a user", async () => {
const waitUntil = vi.fn();
const auth = createAuth(
{
...env,
AUTUMN_SECRET_KEY: "autumn-secret",
AUTUMN_FREE_PLAN_ID: "free",
},
{
waitUntil,
},
);
const hook = (
auth as unknown as {
options: {
databaseHooks?: {
user?: {
create?: {
after?: (
user: { id: string; email?: string | null; name?: string | null },
context?: unknown,
) => Promise<void>;
};
};
};
};
}
).options.databaseHooks?.user?.create?.after;
expect(hook).toEqual(expect.any(Function));
await hook?.(
{
id: "user_123",
email: "user@example.com",
name: "Example User",
},
undefined,
);
expect(waitUntil).toHaveBeenCalledTimes(1);
expect(waitUntil.mock.calls[0]?.[0]).toBeInstanceOf(Promise);
});
});
describe("production auth config", () => {
it("allows the Web Shell origin in Wrangler trusted origins", () => {
const config = JSON.parse(readFileSync("wrangler.jsonc", "utf8")) as {