(client: Client)
| 297 | * idempotency reads against the auth tables Better Auth just migrated. |
| 298 | */ |
| 299 | export const buildBetterAuth = async (client: Client): Promise<BetterAuthHandle> => { |
| 300 | const config = loadConfig(); |
| 301 | |
| 302 | // The org id is resolved by the seed below, AFTER this instance is built; the |
| 303 | // session-pin hook and the gate read it through these late-bound accessors |
| 304 | // (no session is created during the seed, so the empty initial id is never |
| 305 | // observed). `getAuth` resolves to this very instance, so the gate's `after` |
| 306 | // hook can call `auth.api.addMember` once a code is redeemed. |
| 307 | let auth: Auth | null = null; |
| 308 | const orgRef = { id: "" }; |
| 309 | const gate: SignupGate = { |
| 310 | client, |
| 311 | get organizationId() { |
| 312 | return orgRef.id; |
| 313 | }, |
| 314 | getAuth: () => auth, |
| 315 | }; |
| 316 | |
| 317 | auth = createAuthInstance(client, () => orgRef.id, gate); |
| 318 | // `runMigrations()` flows through the LibsqlDialect and is idempotent. |
| 319 | await (await auth.$context).runMigrations(); |
| 320 | await ensureInviteCodeTable(client); |
| 321 | const { organizationId, organizationName } = await seedOrgAndAdmin(auth, client, config); |
| 322 | orgRef.id = organizationId; |
| 323 | |
| 324 | return { |
| 325 | auth, |
| 326 | organizationId, |
| 327 | organizationName, |
| 328 | organizationSlug: config.orgSlug, |
| 329 | handler: auth.handler, |
| 330 | }; |
| 331 | }; |
no test coverage detected