* Set initial tier balance in D1 after user creation. * This guarantees new users get their default tier pollen.
(
env: Cloudflare.Env,
executionCtx?: ExecutionContext,
)
| 206 | * This guarantees new users get their default tier pollen. |
| 207 | */ |
| 208 | function onAfterUserCreate( |
| 209 | env: Cloudflare.Env, |
| 210 | executionCtx?: ExecutionContext, |
| 211 | ) { |
| 212 | return async (user: GenericUser, _ctx: GenericEndpointContext | null) => { |
| 213 | try { |
| 214 | const db = drizzle(env.DB); |
| 215 | const tierBalance = getTierPollen(DEFAULT_TIER); |
| 216 | await db |
| 217 | .update(userTable) |
| 218 | .set({ |
| 219 | tierBalance, |
| 220 | lastTierGrant: Date.now(), |
| 221 | }) |
| 222 | .where(eq(userTable.id, user.id)); |
| 223 | |
| 224 | // Log user registration event to Tinybird |
| 225 | // Use the ExecutionContext passed from createAuth, not better-auth's internal context |
| 226 | executionCtx?.waitUntil( |
| 227 | sendTierEventToTinybird( |
| 228 | { |
| 229 | event_type: "user_registration", |
| 230 | environment: env.ENVIRONMENT || "unknown", |
| 231 | user_id: user.id, |
| 232 | tier: DEFAULT_TIER, |
| 233 | pollen_amount: tierBalance, |
| 234 | }, |
| 235 | env.TINYBIRD_TIER_INGEST_URL, |
| 236 | env.TINYBIRD_INGEST_TOKEN, |
| 237 | ), |
| 238 | ); |
| 239 | } catch (e: unknown) { |
| 240 | const messageOrError = e instanceof Error ? e.message : e; |
| 241 | throw new APIError("INTERNAL_SERVER_ERROR", { |
| 242 | message: `User tier initialization failed. Error: ${messageOrError}`, |
| 243 | }); |
| 244 | } |
| 245 | }; |
| 246 | } |
| 247 | |
| 248 | /** |
| 249 | * Restricts new signups on staging to explicit GitHub ID or email allowlists. |
no test coverage detected