@nwire/auth-better-auth 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/__tests__/auth-better-auth.test.d.ts +11 -0
- package/dist/__tests__/auth-better-auth.test.d.ts.map +1 -0
- package/dist/__tests__/auth-better-auth.test.js +135 -0
- package/dist/__tests__/auth-better-auth.test.js.map +1 -0
- package/dist/auth-better-auth.d.ts +93 -0
- package/dist/auth-better-auth.d.ts.map +1 -0
- package/dist/auth-better-auth.js +131 -0
- package/dist/auth-better-auth.js.map +1 -0
- package/package.json +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Gefter / 200apps Ltd.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @nwire/auth-better-auth
|
|
2
|
+
|
|
3
|
+
> IdP adapter for [better-auth](https://better-auth.com) — the TypeScript-first default.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
Wraps better-auth's API so it conforms to Nwire's `IdpAdapter` contract. Supports `verifyToken`, `signIn`, `signOut`, `register`, `requestPasswordReset`, `resetPassword`. Pairs with Drizzle/Prisma adapters on better-auth's side; the rest of Nwire (RBAC, scoped containers, canonical resolvers) works unchanged.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @nwire/auth-better-auth @nwire/auth better-auth
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick start
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { betterAuth } from "better-auth";
|
|
19
|
+
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
20
|
+
import { betterAuthAdapter } from "@nwire/auth-better-auth";
|
|
21
|
+
import { identityPlugin } from "@nwire/auth";
|
|
22
|
+
import { defineApp } from "@nwire/forge";
|
|
23
|
+
import { db } from "./db.js";
|
|
24
|
+
|
|
25
|
+
const auth = betterAuth({
|
|
26
|
+
database: drizzleAdapter(db, { provider: "pg" }),
|
|
27
|
+
emailAndPassword: { enabled: true },
|
|
28
|
+
socialProviders: { github: { clientId: "...", clientSecret: "..." } },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
defineApp("my-app", {
|
|
32
|
+
plugins: [identityPlugin({ adapter: betterAuthAdapter({ auth }) })],
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API surface
|
|
37
|
+
|
|
38
|
+
- `betterAuthAdapter({ auth })` — produces an `IdpAdapter` that conforms to the `@nwire/auth` contract.
|
|
39
|
+
|
|
40
|
+
## When to use
|
|
41
|
+
|
|
42
|
+
When you want a TS-first auth backend you own the DB schema for. Pair with `@nwire/data-drizzle` for the canonical L3 stack.
|
|
43
|
+
|
|
44
|
+
## Standalone use
|
|
45
|
+
|
|
46
|
+
For developers using `@nwire/auth-better-auth` **without the rest of Nwire** — pair it with any TypeScript project, any container, any HTTP framework.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
// See the package's main entry (src/) for the standalone surface.
|
|
50
|
+
// The exports below work without @nwire/app or @nwire/forge.
|
|
51
|
+
import {} from /* ...standalone exports... */ "@nwire/auth-better-auth";
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Within nwire-app
|
|
55
|
+
|
|
56
|
+
For developers using this package as part of the Nwire stack — register it via `app.use(...)` or it auto-wires when you compose `createApp({ modules })`.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createApp } from "@nwire/forge";
|
|
60
|
+
|
|
61
|
+
const app = createApp({
|
|
62
|
+
/* ...config... */
|
|
63
|
+
});
|
|
64
|
+
// Adapter/plugin wiring happens here when applicable.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## See also
|
|
68
|
+
|
|
69
|
+
- [Architecture sketch §05 — Adapters tier](../../architecture-sketch.html#packages)
|
|
70
|
+
- Sibling packages: [@nwire/auth](../nwire-auth), [@nwire/auth-logto](../nwire-auth-logto), [@nwire/data-drizzle](../nwire-data-drizzle)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter tests — stub better-auth's `api.*` methods directly so the
|
|
3
|
+
* shape mapping is tested without spinning up better-auth itself.
|
|
4
|
+
*
|
|
5
|
+
* better-auth has its own extensive integration tests; we're verifying
|
|
6
|
+
* our glue: that `verifyToken` calls `getSession` with a Bearer header,
|
|
7
|
+
* that the session→User mapping pulls id/email/name + member.role into
|
|
8
|
+
* `roles`, that errors propagate, that optional flows degrade cleanly.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=auth-better-auth.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-better-auth.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auth-better-auth.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter tests — stub better-auth's `api.*` methods directly so the
|
|
3
|
+
* shape mapping is tested without spinning up better-auth itself.
|
|
4
|
+
*
|
|
5
|
+
* better-auth has its own extensive integration tests; we're verifying
|
|
6
|
+
* our glue: that `verifyToken` calls `getSession` with a Bearer header,
|
|
7
|
+
* that the session→User mapping pulls id/email/name + member.role into
|
|
8
|
+
* `roles`, that errors propagate, that optional flows degrade cleanly.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, vi } from "vitest";
|
|
11
|
+
import { betterAuthAdapter } from "../auth-better-auth.js";
|
|
12
|
+
function fakeAuth(api) {
|
|
13
|
+
return { api };
|
|
14
|
+
}
|
|
15
|
+
function fakeSession(overrides = {}) {
|
|
16
|
+
return {
|
|
17
|
+
user: { id: "u_1", email: "alice@example.com", name: "Alice", ...(overrides.user ?? {}) },
|
|
18
|
+
session: {
|
|
19
|
+
id: "s_1",
|
|
20
|
+
token: "tok-1",
|
|
21
|
+
userId: "u_1",
|
|
22
|
+
expiresAt: new Date(Date.now() + 3_600_000),
|
|
23
|
+
...(overrides.session ?? {}),
|
|
24
|
+
},
|
|
25
|
+
member: overrides.member,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
describe("betterAuthAdapter — verifyToken", () => {
|
|
29
|
+
it("returns mapped User when session exists", async () => {
|
|
30
|
+
const getSession = vi.fn().mockResolvedValue(fakeSession());
|
|
31
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ getSession }) });
|
|
32
|
+
const user = await adapter.verifyToken("tok-1");
|
|
33
|
+
expect(user?.id).toBe("u_1");
|
|
34
|
+
expect(user?.email).toBe("alice@example.com");
|
|
35
|
+
expect(user?.name).toBe("Alice");
|
|
36
|
+
expect(user?.roles).toEqual([]);
|
|
37
|
+
expect(getSession).toHaveBeenCalledWith(expect.objectContaining({ headers: expect.any(Headers) }));
|
|
38
|
+
});
|
|
39
|
+
it("returns null when session is null", async () => {
|
|
40
|
+
const getSession = vi.fn().mockResolvedValue(null);
|
|
41
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ getSession }) });
|
|
42
|
+
expect(await adapter.verifyToken("bad")).toBeNull();
|
|
43
|
+
});
|
|
44
|
+
it("returns null when getSession throws", async () => {
|
|
45
|
+
const getSession = vi.fn().mockRejectedValue(new Error("boom"));
|
|
46
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ getSession }) });
|
|
47
|
+
expect(await adapter.verifyToken("x")).toBeNull();
|
|
48
|
+
});
|
|
49
|
+
it("pulls role from active organization member", async () => {
|
|
50
|
+
const getSession = vi.fn().mockResolvedValue(fakeSession({ member: { role: "admin", organizationId: "org_1" } }));
|
|
51
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ getSession }) });
|
|
52
|
+
const user = await adapter.verifyToken("tok-1");
|
|
53
|
+
expect(user?.roles).toEqual(["admin"]);
|
|
54
|
+
});
|
|
55
|
+
it("respects a custom toUser mapper", async () => {
|
|
56
|
+
const getSession = vi.fn().mockResolvedValue(fakeSession());
|
|
57
|
+
const adapter = betterAuthAdapter({
|
|
58
|
+
auth: fakeAuth({ getSession }),
|
|
59
|
+
toUser: (s) => ({
|
|
60
|
+
id: s.user.id,
|
|
61
|
+
email: s.user.email,
|
|
62
|
+
name: (s.user.name ?? "").toUpperCase(),
|
|
63
|
+
roles: ["app:custom"],
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
const user = await adapter.verifyToken("tok-1");
|
|
67
|
+
expect(user?.name).toBe("ALICE");
|
|
68
|
+
expect(user?.roles).toEqual(["app:custom"]);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("betterAuthAdapter — signIn / signOut / register", () => {
|
|
72
|
+
it("signIn calls signInEmail with body + returns user + tokens", async () => {
|
|
73
|
+
const signInEmail = vi.fn().mockResolvedValue(fakeSession());
|
|
74
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ signInEmail }) });
|
|
75
|
+
const result = await adapter.signIn({ email: "alice@example.com", password: "secret" });
|
|
76
|
+
expect(signInEmail).toHaveBeenCalledWith({
|
|
77
|
+
body: { email: "alice@example.com", password: "secret" },
|
|
78
|
+
});
|
|
79
|
+
expect(result.user.id).toBe("u_1");
|
|
80
|
+
expect(result.tokens.accessToken).toBe("tok-1");
|
|
81
|
+
expect(result.tokens.tokenType).toBe("Bearer");
|
|
82
|
+
});
|
|
83
|
+
it("signIn throws when email/password missing", async () => {
|
|
84
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({}) });
|
|
85
|
+
await expect(adapter.signIn({ email: "a@b.c" })).rejects.toThrow(/password/);
|
|
86
|
+
});
|
|
87
|
+
it("signOut calls signOut with Bearer header", async () => {
|
|
88
|
+
const signOut = vi.fn().mockResolvedValue({});
|
|
89
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ signOut }) });
|
|
90
|
+
await adapter.signOut("tok-1");
|
|
91
|
+
const call = signOut.mock.calls[0][0];
|
|
92
|
+
expect(call.headers.get("Authorization")).toBe("Bearer tok-1");
|
|
93
|
+
});
|
|
94
|
+
it("register calls signUpEmail + returns user + initial tokens", async () => {
|
|
95
|
+
const signUpEmail = vi.fn().mockResolvedValue(fakeSession());
|
|
96
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ signUpEmail }) });
|
|
97
|
+
const result = await adapter.register({
|
|
98
|
+
email: "new@example.com",
|
|
99
|
+
password: "long-enough-password",
|
|
100
|
+
name: "New",
|
|
101
|
+
});
|
|
102
|
+
expect(signUpEmail).toHaveBeenCalledWith({
|
|
103
|
+
body: { email: "new@example.com", password: "long-enough-password", name: "New" },
|
|
104
|
+
});
|
|
105
|
+
expect(result.user.id).toBe("u_1");
|
|
106
|
+
expect(result.tokens?.accessToken).toBe("tok-1");
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("betterAuthAdapter — optional flows", () => {
|
|
110
|
+
it("requestPasswordReset throws when not enabled", async () => {
|
|
111
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({}) });
|
|
112
|
+
await expect(adapter.requestPasswordReset("x@y.z")).rejects.toThrow(/reset/);
|
|
113
|
+
});
|
|
114
|
+
it("requestPasswordReset calls forgetPassword when enabled", async () => {
|
|
115
|
+
const forgetPassword = vi.fn().mockResolvedValue({});
|
|
116
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ forgetPassword }) });
|
|
117
|
+
await adapter.requestPasswordReset("alice@example.com");
|
|
118
|
+
expect(forgetPassword).toHaveBeenCalledWith({ body: { email: "alice@example.com" } });
|
|
119
|
+
});
|
|
120
|
+
it("resetPassword calls resetPassword with token + newPassword", async () => {
|
|
121
|
+
const resetPassword = vi.fn().mockResolvedValue({});
|
|
122
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ resetPassword }) });
|
|
123
|
+
await adapter.resetPassword("reset-tok", "newpass-long");
|
|
124
|
+
expect(resetPassword).toHaveBeenCalledWith({
|
|
125
|
+
body: { token: "reset-tok", newPassword: "newpass-long" },
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
it("verifyEmail calls verifyEmail with query token", async () => {
|
|
129
|
+
const verifyEmail = vi.fn().mockResolvedValue({});
|
|
130
|
+
const adapter = betterAuthAdapter({ auth: fakeAuth({ verifyEmail }) });
|
|
131
|
+
await adapter.verifyEmail("v-tok");
|
|
132
|
+
expect(verifyEmail).toHaveBeenCalledWith({ query: { token: "v-tok" } });
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=auth-better-auth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-better-auth.test.js","sourceRoot":"","sources":["../../src/__tests__/auth-better-auth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/auth-better-auth` — IdpAdapter for better-auth.
|
|
3
|
+
*
|
|
4
|
+
* import { betterAuth } from "better-auth";
|
|
5
|
+
* import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
6
|
+
* import { betterAuthAdapter } from "@nwire/auth-better-auth";
|
|
7
|
+
* import { identityPlugin } from "@nwire/auth";
|
|
8
|
+
* import { db } from "./db";
|
|
9
|
+
*
|
|
10
|
+
* const auth = betterAuth({
|
|
11
|
+
* database: drizzleAdapter(db, { provider: "pg" }),
|
|
12
|
+
* emailAndPassword: { enabled: true },
|
|
13
|
+
* socialProviders: { github: { clientId: "...", clientSecret: "..." } },
|
|
14
|
+
* plugins: [organization()],
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* defineApp("my-app", {
|
|
18
|
+
* plugins: [
|
|
19
|
+
* identityPlugin({ adapter: betterAuthAdapter({ auth }) }),
|
|
20
|
+
* ],
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* What it does:
|
|
24
|
+
* - `verifyToken(token)` — calls `auth.api.getSession({ headers })` with
|
|
25
|
+
* a synthesized Bearer header; maps the session's `user` to ours.
|
|
26
|
+
* - `signIn(input)` — `auth.api.signInEmail({ body: { email, password } })`
|
|
27
|
+
* - `signOut(token)` — `auth.api.signOut({ headers })`
|
|
28
|
+
* - `register(input)` — `auth.api.signUpEmail({ body })`
|
|
29
|
+
* - `requestPasswordReset(email)` — `auth.api.forgetPassword`
|
|
30
|
+
* - `resetPassword(token, newPassword)` — `auth.api.resetPassword`
|
|
31
|
+
* - `verifyEmail(token)` — `auth.api.verifyEmail`
|
|
32
|
+
* - `refresh` — not implemented (better-auth uses long-lived sessions
|
|
33
|
+
* or its own refresh-token plugin; pass a refresh adapter explicitly
|
|
34
|
+
* if you've enabled the JWT plugin).
|
|
35
|
+
*
|
|
36
|
+
* Roles map: if you've enabled better-auth's `organization` plugin and
|
|
37
|
+
* `member.role` is populated, this adapter pulls roles from the active
|
|
38
|
+
* organization member record. Otherwise `roles` is `[]` and you wire
|
|
39
|
+
* your own role storage.
|
|
40
|
+
*
|
|
41
|
+
* Why glue: better-auth owns 99% of the work — password hashing, session
|
|
42
|
+
* storage, OAuth providers, magic links, 2FA, passkeys, email
|
|
43
|
+
* verification, organization invitations. We're a thin shape mapper.
|
|
44
|
+
*/
|
|
45
|
+
import type { IdpAdapter, User } from "@nwire/auth";
|
|
46
|
+
/**
|
|
47
|
+
* The minimal shape we need from a better-auth instance — structurally
|
|
48
|
+
* typed so this package doesn't take a hard dep on a specific
|
|
49
|
+
* better-auth version. Authors pass in whatever `betterAuth({...})`
|
|
50
|
+
* returned.
|
|
51
|
+
*/
|
|
52
|
+
export type BetterAuthInstance = {
|
|
53
|
+
readonly api: Record<string, any>;
|
|
54
|
+
};
|
|
55
|
+
interface BetterAuthUser {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly email?: string;
|
|
58
|
+
readonly name?: string;
|
|
59
|
+
readonly emailVerified?: boolean;
|
|
60
|
+
readonly image?: string;
|
|
61
|
+
readonly activeOrganizationId?: string;
|
|
62
|
+
readonly [k: string]: unknown;
|
|
63
|
+
}
|
|
64
|
+
interface BetterAuthSession {
|
|
65
|
+
readonly user: BetterAuthUser;
|
|
66
|
+
readonly session: {
|
|
67
|
+
readonly id: string;
|
|
68
|
+
readonly token: string;
|
|
69
|
+
readonly userId: string;
|
|
70
|
+
readonly expiresAt: string | Date;
|
|
71
|
+
readonly activeOrganizationId?: string;
|
|
72
|
+
};
|
|
73
|
+
readonly member?: {
|
|
74
|
+
readonly role?: string;
|
|
75
|
+
readonly organizationId?: string;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export interface BetterAuthAdapterOptions {
|
|
79
|
+
readonly auth: BetterAuthInstance;
|
|
80
|
+
/**
|
|
81
|
+
* Map a better-auth user (+ session/member) to our canonical User.
|
|
82
|
+
* Default extracts id/email/name + member.role into `roles`. Override
|
|
83
|
+
* when your app has custom user fields, multi-tenant logic, or a
|
|
84
|
+
* different role source.
|
|
85
|
+
*/
|
|
86
|
+
readonly toUser?: (raw: BetterAuthSession) => User;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build the IdpAdapter that wraps a configured better-auth instance.
|
|
90
|
+
*/
|
|
91
|
+
export declare function betterAuthAdapter(options: BetterAuthAdapterOptions): IdpAdapter;
|
|
92
|
+
export {};
|
|
93
|
+
//# sourceMappingURL=auth-better-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-better-auth.d.ts","sourceRoot":"","sources":["../src/auth-better-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,OAAO,KAAK,EAAc,UAAU,EAA8B,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5F;;;;;GAKG;AAEH,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC;AAEvE,UAAU,cAAc;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAExB,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,UAAU,iBAAiB;IACzB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,EAAE,EAAS,MAAM,CAAC;QAC3B,QAAQ,CAAC,KAAK,EAAM,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAK,MAAM,CAAC;QAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;KACxC,CAAC;IAEF,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACpD;AAaD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,UAAU,CAgF/E"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@nwire/auth-better-auth` — IdpAdapter for better-auth.
|
|
3
|
+
*
|
|
4
|
+
* import { betterAuth } from "better-auth";
|
|
5
|
+
* import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
6
|
+
* import { betterAuthAdapter } from "@nwire/auth-better-auth";
|
|
7
|
+
* import { identityPlugin } from "@nwire/auth";
|
|
8
|
+
* import { db } from "./db";
|
|
9
|
+
*
|
|
10
|
+
* const auth = betterAuth({
|
|
11
|
+
* database: drizzleAdapter(db, { provider: "pg" }),
|
|
12
|
+
* emailAndPassword: { enabled: true },
|
|
13
|
+
* socialProviders: { github: { clientId: "...", clientSecret: "..." } },
|
|
14
|
+
* plugins: [organization()],
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* defineApp("my-app", {
|
|
18
|
+
* plugins: [
|
|
19
|
+
* identityPlugin({ adapter: betterAuthAdapter({ auth }) }),
|
|
20
|
+
* ],
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* What it does:
|
|
24
|
+
* - `verifyToken(token)` — calls `auth.api.getSession({ headers })` with
|
|
25
|
+
* a synthesized Bearer header; maps the session's `user` to ours.
|
|
26
|
+
* - `signIn(input)` — `auth.api.signInEmail({ body: { email, password } })`
|
|
27
|
+
* - `signOut(token)` — `auth.api.signOut({ headers })`
|
|
28
|
+
* - `register(input)` — `auth.api.signUpEmail({ body })`
|
|
29
|
+
* - `requestPasswordReset(email)` — `auth.api.forgetPassword`
|
|
30
|
+
* - `resetPassword(token, newPassword)` — `auth.api.resetPassword`
|
|
31
|
+
* - `verifyEmail(token)` — `auth.api.verifyEmail`
|
|
32
|
+
* - `refresh` — not implemented (better-auth uses long-lived sessions
|
|
33
|
+
* or its own refresh-token plugin; pass a refresh adapter explicitly
|
|
34
|
+
* if you've enabled the JWT plugin).
|
|
35
|
+
*
|
|
36
|
+
* Roles map: if you've enabled better-auth's `organization` plugin and
|
|
37
|
+
* `member.role` is populated, this adapter pulls roles from the active
|
|
38
|
+
* organization member record. Otherwise `roles` is `[]` and you wire
|
|
39
|
+
* your own role storage.
|
|
40
|
+
*
|
|
41
|
+
* Why glue: better-auth owns 99% of the work — password hashing, session
|
|
42
|
+
* storage, OAuth providers, magic links, 2FA, passkeys, email
|
|
43
|
+
* verification, organization invitations. We're a thin shape mapper.
|
|
44
|
+
*/
|
|
45
|
+
function defaultToUser(s) {
|
|
46
|
+
const roles = s.member?.role ? [s.member.role] : [];
|
|
47
|
+
return {
|
|
48
|
+
id: s.user.id,
|
|
49
|
+
email: s.user.email,
|
|
50
|
+
name: s.user.name,
|
|
51
|
+
roles,
|
|
52
|
+
tenant: s.session.activeOrganizationId ?? s.user.activeOrganizationId,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build the IdpAdapter that wraps a configured better-auth instance.
|
|
57
|
+
*/
|
|
58
|
+
export function betterAuthAdapter(options) {
|
|
59
|
+
const api = options.auth.api;
|
|
60
|
+
const toUser = options.toUser ?? defaultToUser;
|
|
61
|
+
function bearer(token) {
|
|
62
|
+
const h = new Headers();
|
|
63
|
+
h.set("Authorization", `Bearer ${token}`);
|
|
64
|
+
return h;
|
|
65
|
+
}
|
|
66
|
+
function sessionToTokens(s) {
|
|
67
|
+
const expiresAt = typeof s.session.expiresAt === "string"
|
|
68
|
+
? new Date(s.session.expiresAt).getTime()
|
|
69
|
+
: s.session.expiresAt.getTime();
|
|
70
|
+
return {
|
|
71
|
+
accessToken: s.session.token,
|
|
72
|
+
expiresAt,
|
|
73
|
+
tokenType: "Bearer",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
async verifyToken(token) {
|
|
78
|
+
try {
|
|
79
|
+
const session = (await api.getSession({ headers: bearer(token) }));
|
|
80
|
+
return session ? toUser(session) : null;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
async signIn(input) {
|
|
87
|
+
if (!input.email || !input.password) {
|
|
88
|
+
throw new Error("@nwire/auth-better-auth: signIn requires email + password");
|
|
89
|
+
}
|
|
90
|
+
const result = (await api.signInEmail({
|
|
91
|
+
body: { email: input.email, password: input.password },
|
|
92
|
+
}));
|
|
93
|
+
return { user: toUser(result), tokens: sessionToTokens(result) };
|
|
94
|
+
},
|
|
95
|
+
async signOut(token) {
|
|
96
|
+
await api.signOut({ headers: bearer(token) });
|
|
97
|
+
},
|
|
98
|
+
async register(input) {
|
|
99
|
+
const result = (await api.signUpEmail({
|
|
100
|
+
body: {
|
|
101
|
+
email: input.email,
|
|
102
|
+
password: input.password ?? "",
|
|
103
|
+
name: input.name,
|
|
104
|
+
},
|
|
105
|
+
}));
|
|
106
|
+
return {
|
|
107
|
+
user: toUser(result),
|
|
108
|
+
tokens: result.session ? sessionToTokens(result) : undefined,
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
async requestPasswordReset(email) {
|
|
112
|
+
if (!api.forgetPassword) {
|
|
113
|
+
throw new Error("@nwire/auth-better-auth: enable the email-and-password reset flow first");
|
|
114
|
+
}
|
|
115
|
+
await api.forgetPassword({ body: { email } });
|
|
116
|
+
},
|
|
117
|
+
async resetPassword(resetToken, newPassword) {
|
|
118
|
+
if (!api.resetPassword) {
|
|
119
|
+
throw new Error("@nwire/auth-better-auth: enable the email-and-password reset flow first");
|
|
120
|
+
}
|
|
121
|
+
await api.resetPassword({ body: { token: resetToken, newPassword } });
|
|
122
|
+
},
|
|
123
|
+
async verifyEmail(verificationToken) {
|
|
124
|
+
if (!api.verifyEmail) {
|
|
125
|
+
throw new Error("@nwire/auth-better-auth: email verification not enabled");
|
|
126
|
+
}
|
|
127
|
+
await api.verifyEmail({ query: { token: verificationToken } });
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=auth-better-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-better-auth.js","sourceRoot":"","sources":["../src/auth-better-auth.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nwire/auth-better-auth",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "Nwire — better-auth adapter. Wraps a configured better-auth instance as an IdpAdapter so canonical resolvers (SignIn/SignOut/Register/Refresh/Me/etc.) work against better-auth's database-first auth backend. For self-hosted apps that don't want a separate IdP service.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"adapter",
|
|
7
|
+
"auth",
|
|
8
|
+
"better-auth",
|
|
9
|
+
"idp",
|
|
10
|
+
"nwire"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/auth-better-auth.js",
|
|
18
|
+
"types": "./dist/auth-better-auth.d.ts",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"import": "./dist/auth-better-auth.js",
|
|
22
|
+
"types": "./dist/auth-better-auth.d.ts"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@nwire/auth": "0.7.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.19.9",
|
|
33
|
+
"better-auth": "^1.6.11",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"vitest": "^4.1.6"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"better-auth": ">=1.0.0"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc && node ../../scripts/fix-dist-extensions.mjs dist",
|
|
42
|
+
"dev": "tsc --watch",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
44
|
+
}
|
|
45
|
+
}
|