@next-safe-action/adapter-better-auth 0.1.0 → 0.1.2

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/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <a href="https://github.com/next-safe-action/next-safe-action/packages/adapter-better-auth"><h1>adapter-better-auth</h1></a>
4
4
  </div>
5
5
 
6
- This adapter offers a way to seamlessly integrate [next-safe-action](https://github.com/next-safe-action/next-safe-action) with [Better Auth](https://www.better-auth.com). It provides a `betterAuthMiddleware()` function that fetches the session, blocks unauthenticated requests, and injects fully-typed `{ user, session }` data into the action context.
6
+ This adapter offers a way to seamlessly integrate [next-safe-action](https://github.com/next-safe-action/next-safe-action) with [Better Auth](https://www.better-auth.com). It provides a `betterAuth()` function that fetches the session, blocks unauthenticated requests, and injects fully-typed `{ user, session }` data into the action context.
7
7
 
8
8
  ## Requirements
9
9
 
@@ -37,12 +37,12 @@ export const auth = betterAuth({
37
37
  ```ts
38
38
  // src/lib/safe-action.ts
39
39
  import { createSafeActionClient } from "next-safe-action";
40
- import { betterAuthMiddleware } from "@next-safe-action/adapter-better-auth";
40
+ import { betterAuth } from "@next-safe-action/adapter-better-auth";
41
41
  import { auth } from "./auth";
42
42
 
43
43
  export const actionClient = createSafeActionClient();
44
44
 
45
- export const authClient = actionClient.use(betterAuthMiddleware(auth));
45
+ export const authClient = actionClient.use(betterAuth(auth));
46
46
  ```
47
47
 
48
48
  ### 3. Use it in your actions
@@ -71,7 +71,7 @@ export const updateProfile = authClient
71
71
 
72
72
  ## How it works
73
73
 
74
- `betterAuthMiddleware()` creates a pre-validation middleware for the safe action client's `.use()` chain:
74
+ `betterAuth()` creates a pre-validation middleware for the safe action client's `.use()` chain:
75
75
 
76
76
  1. **Fetches the session** by calling `auth.api.getSession({ headers: await headers() })`
77
77
  2. **Blocks unauthenticated requests** by calling `unauthorized()` from `next/navigation` when no session exists
@@ -100,12 +100,12 @@ Pass an `authorize` callback to customize the authorization flow. The session is
100
100
 
101
101
  ```ts
102
102
  import { unauthorized } from "next/navigation";
103
- import { betterAuthMiddleware } from "@next-safe-action/adapter-better-auth";
103
+ import { betterAuth } from "@next-safe-action/adapter-better-auth";
104
104
  import { auth } from "./auth";
105
105
 
106
106
  // Role-based access
107
107
  export const adminClient = actionClient.use(
108
- betterAuthMiddleware(auth, {
108
+ betterAuth(auth, {
109
109
  authorize: ({ sessionData, next }) => {
110
110
  if (!sessionData || sessionData.user.role !== "admin") {
111
111
  unauthorized();
@@ -143,7 +143,7 @@ export const auth = betterAuth({
143
143
 
144
144
  ## API reference
145
145
 
146
- ### `betterAuthMiddleware(auth, opts?)`
146
+ ### `betterAuth(auth, opts?)`
147
147
 
148
148
  Creates a middleware function for use with the safe action client's `.use()` method.
149
149
 
@@ -158,7 +158,7 @@ Creates a middleware function for use with the safe action client's `.use()` met
158
158
 
159
159
  - `BetterAuthContext<Options>`: the context shape added by the middleware (`{ auth: { user, session } }`)
160
160
  - `AuthorizeFn<Options, NextCtx>`: the `authorize` callback signature
161
- - `BetterAuthMiddlewareOpts<Options, NextCtx>`: the options object type for `betterAuthMiddleware`
161
+ - `BetterAuthOpts<Options, NextCtx>`: the options object type for `betterAuth`
162
162
 
163
163
  ## Documentation
164
164
 
package/dist/index.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- import { Auth, BetterAuthOptions } from "better-auth";
2
1
  import { MiddlewareFn, MiddlewareResult } from "next-safe-action";
2
+ import { Auth, BetterAuthOptions } from "better-auth";
3
3
 
4
4
  //#region src/index.types.d.ts
5
5
  /**
6
- * The default context shape added by `betterAuthMiddleware`.
6
+ * The default context shape added by `betterAuth`.
7
7
  * Contains `auth.user` and `auth.session`, fully typed from the better-auth instance.
8
8
  */
9
9
  type BetterAuthContext<O extends BetterAuthOptions> = {
@@ -11,21 +11,20 @@ type BetterAuthContext<O extends BetterAuthOptions> = {
11
11
  };
12
12
  /**
13
13
  * Authorize callback signature for custom authorization logic.
14
- * Receives the auth instance, pre-fetched session data, current context, and the `next` function.
14
+ * Receives the pre-fetched session data, current context, and the `next` function.
15
15
  */
16
- type AuthorizeFn<O extends BetterAuthOptions, NC extends object> = (args: {
17
- auth: Auth<O>;
16
+ type AuthorizeFn<O extends BetterAuthOptions, NC extends object, Ctx extends object = object> = (args: {
18
17
  sessionData: Auth<O>["$Infer"]["Session"] | null;
19
- ctx: object;
18
+ ctx: Ctx;
20
19
  next: <C extends object>(opts?: {
21
20
  ctx?: C;
22
21
  }) => Promise<MiddlewareResult<any, C>>;
23
22
  }) => Promise<MiddlewareResult<any, NC>>;
24
23
  /**
25
- * Options for `betterAuthMiddleware`.
24
+ * Options for `betterAuth`.
26
25
  */
27
- type BetterAuthMiddlewareOpts<O extends BetterAuthOptions, NC extends object> = {
28
- authorize: AuthorizeFn<O, NC>;
26
+ type BetterAuthOpts<O extends BetterAuthOptions, NC extends object, Ctx extends object = object> = {
27
+ authorize: AuthorizeFn<O, NC, Ctx>;
29
28
  };
30
29
  //#endregion
31
30
  //#region src/index.d.ts
@@ -43,10 +42,10 @@ type BetterAuthMiddlewareOpts<O extends BetterAuthOptions, NC extends object> =
43
42
  * @example
44
43
  * ```ts
45
44
  * // Default: fetch session, unauthorized() if absent
46
- * actionClient.use(betterAuthMiddleware(auth));
45
+ * actionClient.use(betterAuth(auth));
47
46
  *
48
47
  * // Custom: check role
49
- * actionClient.use(betterAuthMiddleware(auth, {
48
+ * actionClient.use(betterAuth(auth, {
50
49
  * authorize: ({ sessionData, next }) => {
51
50
  * if (!sessionData || sessionData.user.role !== "admin") {
52
51
  * unauthorized();
@@ -56,8 +55,8 @@ type BetterAuthMiddlewareOpts<O extends BetterAuthOptions, NC extends object> =
56
55
  * }));
57
56
  * ```
58
57
  */
59
- declare function betterAuthMiddleware<O extends BetterAuthOptions>(auth: Auth<O>): MiddlewareFn<any, any, object, BetterAuthContext<O>>;
60
- declare function betterAuthMiddleware<O extends BetterAuthOptions, NC extends object>(auth: Auth<O>, opts: BetterAuthMiddlewareOpts<O, NC>): MiddlewareFn<any, any, object, NC>;
58
+ declare function betterAuth<O extends BetterAuthOptions>(auth: Auth<O>): MiddlewareFn<any, any, object, BetterAuthContext<O>>;
59
+ declare function betterAuth<O extends BetterAuthOptions, NC extends object, Ctx extends object>(auth: Auth<O>, opts: BetterAuthOpts<O, NC, Ctx>): MiddlewareFn<any, any, Ctx, NC>;
61
60
  //#endregion
62
- export { type AuthorizeFn, type BetterAuthContext, type BetterAuthMiddlewareOpts, betterAuthMiddleware };
61
+ export { type AuthorizeFn, type BetterAuthContext, type BetterAuthOpts, betterAuth };
63
62
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,11 +1,11 @@
1
+ import { createMiddleware } from "next-safe-action";
1
2
  import { headers } from "next/headers.js";
2
3
  import { unauthorized } from "next/navigation.js";
3
4
  //#region src/index.ts
4
- function betterAuthMiddleware(auth, opts) {
5
- return async ({ ctx, next }) => {
5
+ function betterAuth(auth, opts) {
6
+ return createMiddleware().define(async ({ ctx, next }) => {
6
7
  const sessionData = await auth.api.getSession({ headers: await headers() });
7
8
  if (opts?.authorize) return opts.authorize({
8
- auth,
9
9
  sessionData,
10
10
  ctx,
11
11
  next
@@ -15,9 +15,9 @@ function betterAuthMiddleware(auth, opts) {
15
15
  user: sessionData.user,
16
16
  session: sessionData.session
17
17
  } } });
18
- };
18
+ });
19
19
  }
20
20
  //#endregion
21
- export { betterAuthMiddleware };
21
+ export { betterAuth };
22
22
 
23
23
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Auth, BetterAuthOptions } from \"better-auth\";\nimport type { MiddlewareFn } from \"next-safe-action\";\nimport { headers } from \"next/headers\";\nimport { unauthorized } from \"next/navigation\";\nimport type { BetterAuthContext, BetterAuthMiddlewareOpts } from \"./index.types\";\n\n/**\n * Creates a next-safe-action middleware that integrates with better-auth.\n *\n * Default behavior: fetches the session via `auth.api.getSession()`, calls `unauthorized()` if\n * no session exists, and injects `{ auth: { user, session } }` into the action context.\n *\n * Pass an `authorize` callback to customize the authorization flow. The session is pre-fetched\n * and passed to the callback, so common customizations (e.g. role checks) don't need to re-fetch.\n *\n * Note: `unauthorized()` requires `experimental.authInterrupts: true` in your `next.config.ts` file.\n *\n * @example\n * ```ts\n * // Default: fetch session, unauthorized() if absent\n * actionClient.use(betterAuthMiddleware(auth));\n *\n * // Custom: check role\n * actionClient.use(betterAuthMiddleware(auth, {\n * authorize: ({ sessionData, next }) => {\n * if (!sessionData || sessionData.user.role !== \"admin\") {\n * unauthorized();\n * }\n * return next({ ctx: { auth: sessionData } });\n * },\n * }));\n * ```\n */\nexport function betterAuthMiddleware<O extends BetterAuthOptions>(\n\tauth: Auth<O>\n): MiddlewareFn<any, any, object, BetterAuthContext<O>>;\nexport function betterAuthMiddleware<O extends BetterAuthOptions, NC extends object>(\n\tauth: Auth<O>,\n\topts: BetterAuthMiddlewareOpts<O, NC>\n): MiddlewareFn<any, any, object, NC>;\nexport function betterAuthMiddleware<O extends BetterAuthOptions>(\n\tauth: Auth<O>,\n\topts?: BetterAuthMiddlewareOpts<O, any>\n) {\n\treturn async ({ ctx, next }: any) => {\n\t\tconst sessionData = await auth.api.getSession({ headers: await headers() });\n\n\t\tif (opts?.authorize) {\n\t\t\treturn opts.authorize({ auth, sessionData, ctx, next });\n\t\t}\n\n\t\tif (!sessionData) {\n\t\t\tunauthorized();\n\t\t}\n\n\t\treturn next({ ctx: { auth: { user: sessionData.user, session: sessionData.session } } });\n\t};\n}\n\nexport type { AuthorizeFn, BetterAuthContext, BetterAuthMiddlewareOpts } from \"./index.types\";\n"],"mappings":";;;AAwCA,SAAgB,qBACf,MACA,MACC;AACD,QAAO,OAAO,EAAE,KAAK,WAAgB;EACpC,MAAM,cAAc,MAAM,KAAK,IAAI,WAAW,EAAE,SAAS,MAAM,SAAS,EAAE,CAAC;AAE3E,MAAI,MAAM,UACT,QAAO,KAAK,UAAU;GAAE;GAAM;GAAa;GAAK;GAAM,CAAC;AAGxD,MAAI,CAAC,YACJ,eAAc;AAGf,SAAO,KAAK,EAAE,KAAK,EAAE,MAAM;GAAE,MAAM,YAAY;GAAM,SAAS,YAAY;GAAS,EAAE,EAAE,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { Auth, BetterAuthOptions } from \"better-auth\";\nimport { createMiddleware } from \"next-safe-action\";\nimport type { MiddlewareFn } from \"next-safe-action\";\nimport { headers } from \"next/headers\";\nimport { unauthorized } from \"next/navigation\";\nimport type { BetterAuthContext, BetterAuthOpts } from \"./index.types\";\n\n/**\n * Creates a next-safe-action middleware that integrates with better-auth.\n *\n * Default behavior: fetches the session via `auth.api.getSession()`, calls `unauthorized()` if\n * no session exists, and injects `{ auth: { user, session } }` into the action context.\n *\n * Pass an `authorize` callback to customize the authorization flow. The session is pre-fetched\n * and passed to the callback, so common customizations (e.g. role checks) don't need to re-fetch.\n *\n * Note: `unauthorized()` requires `experimental.authInterrupts: true` in your `next.config.ts` file.\n *\n * @example\n * ```ts\n * // Default: fetch session, unauthorized() if absent\n * actionClient.use(betterAuth(auth));\n *\n * // Custom: check role\n * actionClient.use(betterAuth(auth, {\n * authorize: ({ sessionData, next }) => {\n * if (!sessionData || sessionData.user.role !== \"admin\") {\n * unauthorized();\n * }\n * return next({ ctx: { auth: sessionData } });\n * },\n * }));\n * ```\n */\nexport function betterAuth<O extends BetterAuthOptions>(\n\tauth: Auth<O>\n): MiddlewareFn<any, any, object, BetterAuthContext<O>>;\nexport function betterAuth<O extends BetterAuthOptions, NC extends object, Ctx extends object>(\n\tauth: Auth<O>,\n\topts: BetterAuthOpts<O, NC, Ctx>\n): MiddlewareFn<any, any, Ctx, NC>;\nexport function betterAuth<O extends BetterAuthOptions>(\n\tauth: Auth<O>,\n\topts?: BetterAuthOpts<O, any, any>\n) {\n\treturn createMiddleware().define(async ({ ctx, next }) => {\n\t\tconst sessionData = await auth.api.getSession({ headers: await headers() });\n\n\t\tif (opts?.authorize) {\n\t\t\treturn opts.authorize({ sessionData, ctx, next });\n\t\t}\n\n\t\tif (!sessionData) {\n\t\t\tunauthorized();\n\t\t}\n\n\t\treturn next({ ctx: { auth: { user: sessionData.user, session: sessionData.session } } });\n\t});\n}\n\nexport type { AuthorizeFn, BetterAuthContext, BetterAuthOpts } from \"./index.types\";\n"],"mappings":";;;;AAyCA,SAAgB,WACf,MACA,MACC;AACD,QAAO,kBAAkB,CAAC,OAAO,OAAO,EAAE,KAAK,WAAW;EACzD,MAAM,cAAc,MAAM,KAAK,IAAI,WAAW,EAAE,SAAS,MAAM,SAAS,EAAE,CAAC;AAE3E,MAAI,MAAM,UACT,QAAO,KAAK,UAAU;GAAE;GAAa;GAAK;GAAM,CAAC;AAGlD,MAAI,CAAC,YACJ,eAAc;AAGf,SAAO,KAAK,EAAE,KAAK,EAAE,MAAM;GAAE,MAAM,YAAY;GAAM,SAAS,YAAY;GAAS,EAAE,EAAE,CAAC;GACvF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@next-safe-action/adapter-better-auth",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
5
  "description": "Better Auth adapter for next-safe-action.",
6
6
  "main": "./dist/index.mjs",