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