(client: Client)
| 376 | * idempotency reads against the auth tables Better Auth just migrated. |
| 377 | */ |
| 378 | export const buildBetterAuth = async (client: Client): Promise<BetterAuthHandle> => { |
| 379 | const config = loadConfig(); |
| 380 | |
| 381 | // The org id is resolved by the seed below, AFTER this instance is built; the |
| 382 | // session-pin hook and the gate read it through these late-bound accessors |
| 383 | // (no session is created during the seed, so the empty initial id is never |
| 384 | // observed). `getAuth` resolves to this very instance, so the gate's `after` |
| 385 | // hook can call `auth.api.addMember` once a code is redeemed. |
| 386 | let auth: Auth | null = null; |
| 387 | const orgRef = { id: "" }; |
| 388 | const gate: SignupGate = { |
| 389 | client, |
| 390 | get organizationId() { |
| 391 | return orgRef.id; |
| 392 | }, |
| 393 | getAuth: () => auth, |
| 394 | }; |
| 395 | |
| 396 | auth = createAuthInstance(client, () => orgRef.id, gate); |
| 397 | // `runMigrations()` flows through the LibsqlDialect and is idempotent. |
| 398 | await (await auth.$context).runMigrations(); |
| 399 | await ensureInviteCodeTable(client); |
| 400 | const { organizationId, organizationName } = await seedOrgAndAdmin(auth, client, config); |
| 401 | orgRef.id = organizationId; |
| 402 | |
| 403 | return { |
| 404 | auth, |
| 405 | organizationId, |
| 406 | organizationName, |
| 407 | organizationSlug: config.orgSlug, |
| 408 | handler: auth.handler, |
| 409 | }; |
| 410 | }; |
no test coverage detected