@imtf/auth 1.1.0-beta.1 → 2.0.0-beta.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/README.md +164 -0
- package/lib/constants.esm.js +7 -4
- package/lib/hooks/useSignOut.esm.js +68 -55
- package/lib/index.esm.js +2 -8
- package/lib/options/auth-client.esm.js +13 -7
- package/lib/options/auth.esm.js +39 -58
- package/lib/routes/getSignOutUrlRoute.esm.js +49 -59
- package/lib/types/hooks/useSignOut.d.ts +5 -1
- package/lib/types/options/auth-client.d.ts +9 -176
- package/lib/types/options/auth.d.ts +8 -154
- package/lib/types/routes/getSignOutUrlRoute.d.ts +1 -2
- package/package.json +21 -20
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# @imtf/auth - Better Auth wrapper
|
|
2
|
+
|
|
3
|
+
Thin wrapper around [`better-auth`](https://www.better-auth.com/) tailored for IMTF applications. Provides IMTF-specific auth configuration, hooks, and route helpers on top of `better-auth`, for use in Next.js apps.
|
|
4
|
+
|
|
5
|
+
## Pre-requisites
|
|
6
|
+
|
|
7
|
+
The following peer dependencies must be installed:
|
|
8
|
+
|
|
9
|
+
- `better-auth` 1.7.1
|
|
10
|
+
- `zod` 4.3.6 or higher — must stay version-matched with `better-auth`'s own `zod` dependency
|
|
11
|
+
- `@mui/material` 7.1.0 or higher
|
|
12
|
+
- `@mui/lab` 7.0.1-beta.18 or higher
|
|
13
|
+
- `react` and `react-dom` 18.0.0 or 19.0.0 or higher
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @imtf/auth
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
This package supplies IMTF's `better-auth` configuration and a couple of OIDC-flow helpers — it does not wrap `betterAuth()`/`createAuthClient()` themselves. Call those directly with the options this package returns.
|
|
24
|
+
|
|
25
|
+
### Server: `auth.ts`
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import "server-only";
|
|
29
|
+
|
|
30
|
+
import { getBetterAuthOptions } from "@imtf/auth";
|
|
31
|
+
import { betterAuth, type BetterAuthOptions } from "better-auth";
|
|
32
|
+
|
|
33
|
+
export const auth = betterAuth({
|
|
34
|
+
...getBetterAuthOptions({
|
|
35
|
+
oidcDiscoveryUrl: `${process.env.OIDC_ISSUER_URL}/.well-known/openid-configuration`,
|
|
36
|
+
authSecret: process.env.AUTH_SECRET!,
|
|
37
|
+
authClientId: process.env.OIDC_CLIENT_ID!,
|
|
38
|
+
authClientSecret: process.env.OIDC_CLIENT_SECRET!,
|
|
39
|
+
authBaseURL: process.env.AUTH_BASE_URL,
|
|
40
|
+
}),
|
|
41
|
+
} satisfies BetterAuthOptions);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Client: `auth-client.ts`
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
"use client";
|
|
48
|
+
|
|
49
|
+
import { createAuthClient } from "better-auth/react";
|
|
50
|
+
|
|
51
|
+
export const authClient = createAuthClient();
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Route handler: `app/api/auth/[...all]/route.ts`
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import type { NextRequest } from "next/server";
|
|
58
|
+
import { auth } from "@/auth";
|
|
59
|
+
|
|
60
|
+
function handler(request: NextRequest) {
|
|
61
|
+
return auth.handler(request);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const GET = handler;
|
|
65
|
+
export const POST = handler;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Federated sign-out route: `app/api/auth/sign-out-url/route.ts`
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { getSignOutUrlRoute } from "@imtf/auth";
|
|
72
|
+
import { headers } from "next/headers";
|
|
73
|
+
import { auth } from "@/auth";
|
|
74
|
+
|
|
75
|
+
export const GET = getSignOutUrlRoute({
|
|
76
|
+
auth,
|
|
77
|
+
discoveryUrl: `${process.env.OIDC_ISSUER_URL}/.well-known/openid-configuration`,
|
|
78
|
+
headers,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Session check in a server component
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { headers } from "next/headers";
|
|
86
|
+
import { redirect } from "next/navigation";
|
|
87
|
+
import { auth } from "@/auth";
|
|
88
|
+
|
|
89
|
+
export async function AuthGuard({ children }: { children: React.ReactNode }) {
|
|
90
|
+
const { accessToken } = await auth.api
|
|
91
|
+
.getAccessToken({ body: { useAccountCookie: true }, headers: await headers() })
|
|
92
|
+
.catch(() => ({ accessToken: undefined }));
|
|
93
|
+
|
|
94
|
+
if (!accessToken) redirect("/auth/sign-in");
|
|
95
|
+
|
|
96
|
+
return children;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Sign-in and sign-out (client components)
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
"use client";
|
|
104
|
+
|
|
105
|
+
import { PROVIDER_ID, useSignOut } from "@imtf/auth";
|
|
106
|
+
import { authClient } from "@/auth-client";
|
|
107
|
+
|
|
108
|
+
function SignInButton() {
|
|
109
|
+
const handleSignIn = () =>
|
|
110
|
+
void authClient.signIn.social({ provider: PROVIDER_ID, callbackURL: "/" });
|
|
111
|
+
|
|
112
|
+
return <button onClick={handleSignIn}>Sign in</button>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function SignOutButton() {
|
|
116
|
+
const { handleSignOut } = useSignOut({ authClient });
|
|
117
|
+
|
|
118
|
+
return <button onClick={handleSignOut}>Sign out</button>;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Full export list
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import {
|
|
126
|
+
getBetterAuthOptions,
|
|
127
|
+
getBetterAuthClientOptions,
|
|
128
|
+
getSignOutUrlRoute,
|
|
129
|
+
useSignOut,
|
|
130
|
+
PROVIDER_ID,
|
|
131
|
+
} from "@imtf/auth";
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
> `getBetterAuthClientOptions` is deprecated as of `better-auth` 1.7 — generic OAuth sign-in no longer needs a client plugin, so `createAuthClient()` can be called with no options as shown above.
|
|
135
|
+
|
|
136
|
+
## Development
|
|
137
|
+
|
|
138
|
+
Prior to development, make sure you have installed the dependencies from the **repository root**:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pnpm install
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Testing
|
|
145
|
+
|
|
146
|
+
To run the tests, just run:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
pnpm run test
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Coverage report can be generated with:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
pnpm run test:coverage
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Migration from v1 to v2
|
|
159
|
+
|
|
160
|
+
`@imtf/auth` v2 upgrades its `better-auth` peer dependency from `1.6.30` to `1.7.1`. `better-auth` 1.7 rewrote the generic OAuth plugin as a first-class social provider — see the [Better Auth 1.7 upgrade guide](https://www.better-auth.com/docs/guides/1-7-upgrade-guide) for the full list of breaking changes upstream. The changes relevant to consumers of this package are:
|
|
161
|
+
|
|
162
|
+
- **OAuth callback URL path changed.** The redirect URI that `better-auth` exposes for the generic OIDC provider moved from `{baseURL}/oauth2/callback/{providerId}` to `{baseURL}/callback/{providerId}` (e.g. `https://app.example.com/api/auth/oauth2/callback/oidc-provider` → `https://app.example.com/api/auth/callback/oidc-provider`). **You must update the redirect URI registered with your OIDC provider/IdP client** before deploying this upgrade, or sign-in will fail.
|
|
163
|
+
- **`getSignOutUrlRoute` dropped its `providerId` option.** `better-auth`'s `getAccessToken` API no longer accepts `providerId` to select an account; it now resolves the account from the signed account cookie (`useAccountCookie: true`), matching this package's database-less, `storeAccountCookie: true` configuration. If you were passing `providerId` to `getSignOutUrlRoute`, remove it — it is no longer read.
|
|
164
|
+
- **No client plugin is required for generic OAuth sign-in anymore.** `getBetterAuthClientOptions()` no longer registers `genericOAuthClient()` (removed upstream). Generic/custom OAuth providers now sign in through the standard `authClient.signIn.social({ provider })` / `authClient.linkSocial({ provider })` methods. No action needed on your end beyond upgrading — this package's exported options already reflect the change.
|
package/lib/constants.esm.js
CHANGED
|
@@ -1,57 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { useCallback } from "react";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
3
|
+
//#region src/hooks/useSignOut.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Custom hook for handling user sign-out with support for federated logout.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* const { handleSignOut } = useSignOut({ postSignOutRedirectPath: "/auth/sign-in?sign-out=success" });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
function useSignOut({ postSignOutRedirectPath = "/auth/sign-in?sign-out=success", retrieveSignOutUrlPath = "/api/auth/sign-out-url", onSignOutStart, onSignOutSuccess, authClient, origin: providedOrigin }) {
|
|
13
|
+
const origin = providedOrigin ?? (typeof window !== "undefined" ? window.location.origin : "");
|
|
14
|
+
/**
|
|
15
|
+
* Performs a standard (non-federated) sign-out and redirects to the sign-in page.
|
|
16
|
+
*/
|
|
17
|
+
const standardSignOut = useCallback(() => {
|
|
18
|
+
onSignOutStart?.();
|
|
19
|
+
authClient.signOut({ fetchOptions: { onSuccess: onSignOutSuccess } });
|
|
20
|
+
}, [
|
|
21
|
+
authClient,
|
|
22
|
+
onSignOutStart,
|
|
23
|
+
onSignOutSuccess
|
|
24
|
+
]);
|
|
25
|
+
return { handleSignOut: useCallback(async () => {
|
|
26
|
+
const postLogoutRedirectUri = `${origin}${postSignOutRedirectPath}`;
|
|
27
|
+
/**
|
|
28
|
+
* Attempt federated logout. This is, surprisingly, not built into better-auth:
|
|
29
|
+
*/
|
|
30
|
+
try {
|
|
31
|
+
/**
|
|
32
|
+
* Create a logout URL before we invoke authClient.signOut(), since it clears critical tokens.
|
|
33
|
+
*/
|
|
34
|
+
const response = await fetch(`${origin}${retrieveSignOutUrlPath}?post_logout_redirect_uri=${encodeURIComponent(postLogoutRedirectUri)}`);
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
const errorBody = await response.json().catch(() => null);
|
|
37
|
+
const error = errorBody !== null && typeof errorBody === "object" && "error" in errorBody && typeof errorBody.error === "string" ? errorBody.error : null;
|
|
38
|
+
throw new Error(error ?? "Failed to create logout URL");
|
|
39
|
+
}
|
|
40
|
+
const responseBody = await response.json();
|
|
41
|
+
const url = responseBody !== null && typeof responseBody === "object" && "url" in responseBody && typeof responseBody.url === "string" ? responseBody.url : null;
|
|
42
|
+
if (!url) {
|
|
43
|
+
standardSignOut();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sign out from better-auth, then redirect the user to the OIDC provider's
|
|
48
|
+
* end_session_endpoint to terminate the federated session. The provider
|
|
49
|
+
* should automatically redirect back to the application after logout.
|
|
50
|
+
*/
|
|
51
|
+
await authClient.signOut();
|
|
52
|
+
if (typeof window === "undefined") return;
|
|
53
|
+
window.location.href = url;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error("Error during federated logout, switching to standard logout:", error);
|
|
56
|
+
/**
|
|
57
|
+
* Fallback: Standard logout
|
|
58
|
+
*/
|
|
59
|
+
standardSignOut();
|
|
60
|
+
}
|
|
61
|
+
}, [
|
|
62
|
+
authClient,
|
|
63
|
+
origin,
|
|
64
|
+
postSignOutRedirectPath,
|
|
65
|
+
retrieveSignOutUrlPath,
|
|
66
|
+
standardSignOut
|
|
67
|
+
]) };
|
|
54
68
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
};
|
|
69
|
+
//#endregion
|
|
70
|
+
export { useSignOut };
|
package/lib/index.esm.js
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
|
+
import { PROVIDER_ID } from "./constants.esm.js";
|
|
1
2
|
import { getBetterAuthOptions } from "./options/auth.esm.js";
|
|
2
3
|
import { getBetterAuthClientOptions } from "./options/auth-client.esm.js";
|
|
3
4
|
import { getSignOutUrlRoute } from "./routes/getSignOutUrlRoute.esm.js";
|
|
4
|
-
import { PROVIDER_ID } from "./constants.esm.js";
|
|
5
5
|
import { useSignOut } from "./hooks/useSignOut.esm.js";
|
|
6
|
-
export {
|
|
7
|
-
PROVIDER_ID,
|
|
8
|
-
getBetterAuthClientOptions,
|
|
9
|
-
getBetterAuthOptions,
|
|
10
|
-
getSignOutUrlRoute,
|
|
11
|
-
useSignOut
|
|
12
|
-
};
|
|
6
|
+
export { PROVIDER_ID, getBetterAuthClientOptions, getBetterAuthOptions, getSignOutUrlRoute, useSignOut };
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
//#region src/options/auth-client.ts
|
|
3
|
+
/**
|
|
4
|
+
* Generic OAuth providers sign in through the standard `signIn.social` /
|
|
5
|
+
* `linkSocial` client methods (better-auth 1.7+), so no client plugin is
|
|
6
|
+
* required.
|
|
7
|
+
*
|
|
8
|
+
* @deprecated No longer needed — pass options directly to `createAuthClient`
|
|
9
|
+
* instead. Will be removed in a future major version.
|
|
10
|
+
*/
|
|
2
11
|
function getBetterAuthClientOptions() {
|
|
3
|
-
|
|
4
|
-
plugins: [genericOAuthClient()]
|
|
5
|
-
};
|
|
12
|
+
return {};
|
|
6
13
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
14
|
+
//#endregion
|
|
15
|
+
export { getBetterAuthClientOptions };
|
package/lib/options/auth.esm.js
CHANGED
|
@@ -1,61 +1,42 @@
|
|
|
1
|
+
import { PROVIDER_ID } from "../constants.esm.js";
|
|
1
2
|
import { nextCookies } from "better-auth/next-js";
|
|
2
3
|
import { genericOAuth } from "better-auth/plugins";
|
|
3
|
-
|
|
4
|
-
function getBetterAuthOptions({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
genericOAuth({
|
|
40
|
-
config: [
|
|
41
|
-
{
|
|
42
|
-
providerId,
|
|
43
|
-
clientId: authClientId,
|
|
44
|
-
clientSecret: authClientSecret,
|
|
45
|
-
discoveryUrl: oidcDiscoveryUrl,
|
|
46
|
-
scopes: ["openid"],
|
|
47
|
-
pkce: true
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}),
|
|
51
|
-
// Next.js cookie integration for server actions and middleware
|
|
52
|
-
nextCookies()
|
|
53
|
-
],
|
|
54
|
-
onAPIError: {
|
|
55
|
-
errorURL: "/auth/error"
|
|
56
|
-
}
|
|
57
|
-
};
|
|
4
|
+
//#region src/options/auth.ts
|
|
5
|
+
function getBetterAuthOptions({ oidcDiscoveryUrl, authSecret, authBaseURL, authClientId, authClientSecret, providerId = PROVIDER_ID }) {
|
|
6
|
+
/**
|
|
7
|
+
* Better-auth configuration with OIDC/OAuth2 support.
|
|
8
|
+
* Uses cookie-based session storage for database-less authentication.
|
|
9
|
+
*/
|
|
10
|
+
return {
|
|
11
|
+
secret: authSecret,
|
|
12
|
+
baseURL: authBaseURL,
|
|
13
|
+
session: {
|
|
14
|
+
cookieCache: {
|
|
15
|
+
enabled: true,
|
|
16
|
+
version: "1",
|
|
17
|
+
maxAge: 86400,
|
|
18
|
+
strategy: "jwe",
|
|
19
|
+
refreshCache: true
|
|
20
|
+
},
|
|
21
|
+
expiresIn: 86400,
|
|
22
|
+
updateAge: 3600,
|
|
23
|
+
freshAge: 300
|
|
24
|
+
},
|
|
25
|
+
account: {
|
|
26
|
+
updateAccountOnSignIn: true,
|
|
27
|
+
storeStateStrategy: "cookie",
|
|
28
|
+
storeAccountCookie: true
|
|
29
|
+
},
|
|
30
|
+
plugins: [genericOAuth({ config: [{
|
|
31
|
+
providerId,
|
|
32
|
+
clientId: authClientId,
|
|
33
|
+
clientSecret: authClientSecret,
|
|
34
|
+
discoveryUrl: oidcDiscoveryUrl,
|
|
35
|
+
scopes: ["openid"],
|
|
36
|
+
pkce: true
|
|
37
|
+
}] }), nextCookies()],
|
|
38
|
+
onAPIError: { errorURL: "/auth/error" }
|
|
39
|
+
};
|
|
58
40
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
};
|
|
41
|
+
//#endregion
|
|
42
|
+
export { getBetterAuthOptions };
|
|
@@ -1,60 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
function getSignOutUrlRoute({
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return Response.json({ url: logoutUrl.toString() });
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error("Failed to construct logout URL:", error);
|
|
51
|
-
return Response.json(
|
|
52
|
-
{ error: "Failed to construct logout URL" },
|
|
53
|
-
{ status: 500 }
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
};
|
|
1
|
+
//#region src/routes/getSignOutUrlRoute.ts
|
|
2
|
+
function getSignOutUrlRoute({ auth, discoveryUrl, federatedLogout = true, headers }) {
|
|
3
|
+
/**
|
|
4
|
+
* API route that constructs a federated logout URL for OIDC providers.
|
|
5
|
+
* Returns null if federated logout is disabled.
|
|
6
|
+
*
|
|
7
|
+
* @param request - Next.js request object with optional post_logout_redirect_uri parameter
|
|
8
|
+
* @returns JSON response with logout URL or error
|
|
9
|
+
*/
|
|
10
|
+
return async function GET(request) {
|
|
11
|
+
try {
|
|
12
|
+
if (!federatedLogout || !discoveryUrl) return Response.json({ url: null }, { status: 200 });
|
|
13
|
+
/**
|
|
14
|
+
* Retrieve the user's ID token, to produce a valid logout URL.
|
|
15
|
+
* `useAccountCookie` reads the single OAuth account stored in the
|
|
16
|
+
* signed cookie (database-less flow), matching `storeAccountCookie`.
|
|
17
|
+
*/
|
|
18
|
+
const token = await auth.api.getAccessToken({
|
|
19
|
+
body: { useAccountCookie: true },
|
|
20
|
+
headers: await headers()
|
|
21
|
+
}).catch(() => null);
|
|
22
|
+
if (!token?.idToken) return Response.json({ error: "No ID token found for user" }, { status: 400 });
|
|
23
|
+
/**
|
|
24
|
+
* Fetch the well-known configuration from the OIDC provider to construct the
|
|
25
|
+
* logout URL.
|
|
26
|
+
*/
|
|
27
|
+
const wellKnownResponse = await fetch(discoveryUrl);
|
|
28
|
+
if (!wellKnownResponse.ok) return Response.json({ error: "Failed to fetch OIDC discovery document" }, { status: 500 });
|
|
29
|
+
const wellKnownConfigJson = await wellKnownResponse.json();
|
|
30
|
+
const endSessionEndpoint = wellKnownConfigJson !== null && typeof wellKnownConfigJson === "object" && "end_session_endpoint" in wellKnownConfigJson && typeof wellKnownConfigJson.end_session_endpoint === "string" ? wellKnownConfigJson.end_session_endpoint : void 0;
|
|
31
|
+
if (!endSessionEndpoint) return Response.json({ error: "Could not determine end_session_endpoint" }, { status: 500 });
|
|
32
|
+
/**
|
|
33
|
+
* Construct the logout URL with parameters.
|
|
34
|
+
* - end_session_endpoint: The OIDC provider's end_session_endpoint.
|
|
35
|
+
* - post_logout_redirect_uri: The URL to redirect to after logout.
|
|
36
|
+
* - id_token_hint: The user's ID token.
|
|
37
|
+
*/
|
|
38
|
+
const logoutUrl = new URL(endSessionEndpoint);
|
|
39
|
+
const postLogoutRedirectUri = request.nextUrl.searchParams.get("post_logout_redirect_uri") ?? "/auth/sign-in";
|
|
40
|
+
logoutUrl.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUri);
|
|
41
|
+
logoutUrl.searchParams.set("id_token_hint", token.idToken);
|
|
42
|
+
return Response.json({ url: logoutUrl.toString() });
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.error("Failed to construct logout URL:", error);
|
|
45
|
+
return Response.json({ error: "Failed to construct logout URL" }, { status: 500 });
|
|
46
|
+
}
|
|
47
|
+
};
|
|
57
48
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { getSignOutUrlRoute };
|
|
@@ -21,7 +21,11 @@ export type UseSignOutOptions = {
|
|
|
21
21
|
*/
|
|
22
22
|
authClient: ReturnType<typeof createAuthClient>;
|
|
23
23
|
/**
|
|
24
|
-
* Optional origin
|
|
24
|
+
* Optional origin (and, if applicable, base path) prepended to both
|
|
25
|
+
* `retrieveSignOutUrlPath` and `postSignOutRedirectPath`. Defaults to the
|
|
26
|
+
* current window location origin. Useful when the app is served under a
|
|
27
|
+
* base path, since these URLs are built outside Next's router and don't
|
|
28
|
+
* get it auto-applied.
|
|
25
29
|
*/
|
|
26
30
|
origin?: string;
|
|
27
31
|
};
|
|
@@ -1,176 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
endpoints: {
|
|
12
|
-
signInWithOAuth2: import("better-call").StrictEndpoint<"/sign-in/oauth2", {
|
|
13
|
-
method: "POST";
|
|
14
|
-
body: import("zod").ZodObject<{
|
|
15
|
-
providerId: import("zod").ZodString;
|
|
16
|
-
callbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
17
|
-
errorCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
18
|
-
newUserCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
19
|
-
disableRedirect: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
20
|
-
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
21
|
-
requestSignUp: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
22
|
-
additionalData: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
|
|
23
|
-
}, import("better-auth").$strip>;
|
|
24
|
-
metadata: {
|
|
25
|
-
openapi: {
|
|
26
|
-
description: string;
|
|
27
|
-
responses: {
|
|
28
|
-
200: {
|
|
29
|
-
description: string;
|
|
30
|
-
content: {
|
|
31
|
-
"application/json": {
|
|
32
|
-
schema: {
|
|
33
|
-
type: "object";
|
|
34
|
-
properties: {
|
|
35
|
-
url: {
|
|
36
|
-
type: string;
|
|
37
|
-
};
|
|
38
|
-
redirect: {
|
|
39
|
-
type: string;
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
}, {
|
|
50
|
-
url: string;
|
|
51
|
-
redirect: boolean;
|
|
52
|
-
}>;
|
|
53
|
-
oAuth2Callback: import("better-call").StrictEndpoint<"/oauth2/callback/:providerId", {
|
|
54
|
-
method: "GET";
|
|
55
|
-
query: import("zod").ZodObject<{
|
|
56
|
-
code: import("zod").ZodOptional<import("zod").ZodString>;
|
|
57
|
-
error: import("zod").ZodOptional<import("zod").ZodString>;
|
|
58
|
-
error_description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
59
|
-
state: import("zod").ZodOptional<import("zod").ZodString>;
|
|
60
|
-
iss: import("zod").ZodOptional<import("zod").ZodString>;
|
|
61
|
-
}, import("better-auth").$strip>;
|
|
62
|
-
metadata: {
|
|
63
|
-
allowedMediaTypes: string[];
|
|
64
|
-
openapi: {
|
|
65
|
-
description: string;
|
|
66
|
-
responses: {
|
|
67
|
-
200: {
|
|
68
|
-
description: string;
|
|
69
|
-
content: {
|
|
70
|
-
"application/json": {
|
|
71
|
-
schema: {
|
|
72
|
-
type: "object";
|
|
73
|
-
properties: {
|
|
74
|
-
url: {
|
|
75
|
-
type: string;
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
scope: "server";
|
|
85
|
-
};
|
|
86
|
-
}, void>;
|
|
87
|
-
oAuth2LinkAccount: import("better-call").StrictEndpoint<"/oauth2/link", {
|
|
88
|
-
method: "POST";
|
|
89
|
-
body: import("zod").ZodObject<{
|
|
90
|
-
providerId: import("zod").ZodString;
|
|
91
|
-
callbackURL: import("zod").ZodString;
|
|
92
|
-
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
93
|
-
errorCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
94
|
-
}, import("better-auth").$strip>;
|
|
95
|
-
use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
|
|
96
|
-
session: {
|
|
97
|
-
session: Record<string, any> & {
|
|
98
|
-
id: string;
|
|
99
|
-
createdAt: Date;
|
|
100
|
-
updatedAt: Date;
|
|
101
|
-
userId: string;
|
|
102
|
-
expiresAt: Date;
|
|
103
|
-
token: string;
|
|
104
|
-
ipAddress?: string | null | undefined;
|
|
105
|
-
userAgent?: string | null | undefined;
|
|
106
|
-
};
|
|
107
|
-
user: Record<string, any> & {
|
|
108
|
-
id: string;
|
|
109
|
-
createdAt: Date;
|
|
110
|
-
updatedAt: Date;
|
|
111
|
-
email: string;
|
|
112
|
-
emailVerified: boolean;
|
|
113
|
-
name: string;
|
|
114
|
-
image?: string | null | undefined;
|
|
115
|
-
};
|
|
116
|
-
};
|
|
117
|
-
}>)[];
|
|
118
|
-
metadata: {
|
|
119
|
-
openapi: {
|
|
120
|
-
description: string;
|
|
121
|
-
responses: {
|
|
122
|
-
"200": {
|
|
123
|
-
description: string;
|
|
124
|
-
content: {
|
|
125
|
-
"application/json": {
|
|
126
|
-
schema: {
|
|
127
|
-
type: "object";
|
|
128
|
-
properties: {
|
|
129
|
-
url: {
|
|
130
|
-
type: string;
|
|
131
|
-
format: string;
|
|
132
|
-
description: string;
|
|
133
|
-
};
|
|
134
|
-
redirect: {
|
|
135
|
-
type: string;
|
|
136
|
-
description: string;
|
|
137
|
-
enum: boolean[];
|
|
138
|
-
};
|
|
139
|
-
};
|
|
140
|
-
required: string[];
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
};
|
|
144
|
-
};
|
|
145
|
-
};
|
|
146
|
-
};
|
|
147
|
-
};
|
|
148
|
-
}, {
|
|
149
|
-
url: string;
|
|
150
|
-
redirect: boolean;
|
|
151
|
-
}>;
|
|
152
|
-
};
|
|
153
|
-
options: import("better-auth/plugins").GenericOAuthOptions;
|
|
154
|
-
$ERROR_CODES: {
|
|
155
|
-
INVALID_OAUTH_CONFIGURATION: import("better-auth").RawError<"INVALID_OAUTH_CONFIGURATION">;
|
|
156
|
-
TOKEN_URL_NOT_FOUND: import("better-auth").RawError<"TOKEN_URL_NOT_FOUND">;
|
|
157
|
-
PROVIDER_CONFIG_NOT_FOUND: import("better-auth").RawError<"PROVIDER_CONFIG_NOT_FOUND">;
|
|
158
|
-
PROVIDER_ID_REQUIRED: import("better-auth").RawError<"PROVIDER_ID_REQUIRED">;
|
|
159
|
-
INVALID_OAUTH_CONFIG: import("better-auth").RawError<"INVALID_OAUTH_CONFIG">;
|
|
160
|
-
SESSION_REQUIRED: import("better-auth").RawError<"SESSION_REQUIRED">;
|
|
161
|
-
ISSUER_MISMATCH: import("better-auth").RawError<"ISSUER_MISMATCH">;
|
|
162
|
-
ISSUER_MISSING: import("better-auth").RawError<"ISSUER_MISSING">;
|
|
163
|
-
};
|
|
164
|
-
}>;
|
|
165
|
-
$ERROR_CODES: {
|
|
166
|
-
INVALID_OAUTH_CONFIGURATION: import("better-auth").RawError<"INVALID_OAUTH_CONFIGURATION">;
|
|
167
|
-
TOKEN_URL_NOT_FOUND: import("better-auth").RawError<"TOKEN_URL_NOT_FOUND">;
|
|
168
|
-
PROVIDER_CONFIG_NOT_FOUND: import("better-auth").RawError<"PROVIDER_CONFIG_NOT_FOUND">;
|
|
169
|
-
PROVIDER_ID_REQUIRED: import("better-auth").RawError<"PROVIDER_ID_REQUIRED">;
|
|
170
|
-
INVALID_OAUTH_CONFIG: import("better-auth").RawError<"INVALID_OAUTH_CONFIG">;
|
|
171
|
-
SESSION_REQUIRED: import("better-auth").RawError<"SESSION_REQUIRED">;
|
|
172
|
-
ISSUER_MISMATCH: import("better-auth").RawError<"ISSUER_MISMATCH">;
|
|
173
|
-
ISSUER_MISSING: import("better-auth").RawError<"ISSUER_MISSING">;
|
|
174
|
-
};
|
|
175
|
-
}];
|
|
176
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Generic OAuth providers sign in through the standard `signIn.social` /
|
|
3
|
+
* `linkSocial` client methods (better-auth 1.7+), so no client plugin is
|
|
4
|
+
* required.
|
|
5
|
+
*
|
|
6
|
+
* @deprecated No longer needed — pass options directly to `createAuthClient`
|
|
7
|
+
* instead. Will be removed in a future major version.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getBetterAuthClientOptions(): {};
|
|
@@ -27,174 +27,28 @@ export declare function getBetterAuthOptions({ oidcDiscoveryUrl, authSecret, aut
|
|
|
27
27
|
};
|
|
28
28
|
readonly plugins: [{
|
|
29
29
|
id: "generic-oauth";
|
|
30
|
-
|
|
30
|
+
version: string;
|
|
31
|
+
init: (ctx: import("better-auth").AuthContext) => Promise<{
|
|
31
32
|
context: {
|
|
32
|
-
socialProviders: import("better-auth").OAuthProvider<
|
|
33
|
+
socialProviders: import("better-auth").OAuthProvider<object, Partial<import("better-auth").ProviderOptions<object>>>[];
|
|
33
34
|
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
signInWithOAuth2: import("better-call").StrictEndpoint<"/sign-in/oauth2", {
|
|
37
|
-
method: "POST";
|
|
38
|
-
body: import("zod").ZodObject<{
|
|
39
|
-
providerId: import("zod").ZodString;
|
|
40
|
-
callbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
41
|
-
errorCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
42
|
-
newUserCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
43
|
-
disableRedirect: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
44
|
-
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
45
|
-
requestSignUp: import("zod").ZodOptional<import("zod").ZodBoolean>;
|
|
46
|
-
additionalData: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodAny>>;
|
|
47
|
-
}, import("better-auth").$strip>;
|
|
48
|
-
metadata: {
|
|
49
|
-
openapi: {
|
|
50
|
-
description: string;
|
|
51
|
-
responses: {
|
|
52
|
-
200: {
|
|
53
|
-
description: string;
|
|
54
|
-
content: {
|
|
55
|
-
"application/json": {
|
|
56
|
-
schema: {
|
|
57
|
-
type: "object";
|
|
58
|
-
properties: {
|
|
59
|
-
url: {
|
|
60
|
-
type: string;
|
|
61
|
-
};
|
|
62
|
-
redirect: {
|
|
63
|
-
type: string;
|
|
64
|
-
};
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
}, {
|
|
74
|
-
url: string;
|
|
75
|
-
redirect: boolean;
|
|
76
|
-
}>;
|
|
77
|
-
oAuth2Callback: import("better-call").StrictEndpoint<"/oauth2/callback/:providerId", {
|
|
78
|
-
method: "GET";
|
|
79
|
-
query: import("zod").ZodObject<{
|
|
80
|
-
code: import("zod").ZodOptional<import("zod").ZodString>;
|
|
81
|
-
error: import("zod").ZodOptional<import("zod").ZodString>;
|
|
82
|
-
error_description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
83
|
-
state: import("zod").ZodOptional<import("zod").ZodString>;
|
|
84
|
-
iss: import("zod").ZodOptional<import("zod").ZodString>;
|
|
85
|
-
}, import("better-auth").$strip>;
|
|
86
|
-
metadata: {
|
|
87
|
-
allowedMediaTypes: string[];
|
|
88
|
-
openapi: {
|
|
89
|
-
description: string;
|
|
90
|
-
responses: {
|
|
91
|
-
200: {
|
|
92
|
-
description: string;
|
|
93
|
-
content: {
|
|
94
|
-
"application/json": {
|
|
95
|
-
schema: {
|
|
96
|
-
type: "object";
|
|
97
|
-
properties: {
|
|
98
|
-
url: {
|
|
99
|
-
type: string;
|
|
100
|
-
};
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
scope: "server";
|
|
109
|
-
};
|
|
110
|
-
}, void>;
|
|
111
|
-
oAuth2LinkAccount: import("better-call").StrictEndpoint<"/oauth2/link", {
|
|
112
|
-
method: "POST";
|
|
113
|
-
body: import("zod").ZodObject<{
|
|
114
|
-
providerId: import("zod").ZodString;
|
|
115
|
-
callbackURL: import("zod").ZodString;
|
|
116
|
-
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
117
|
-
errorCallbackURL: import("zod").ZodOptional<import("zod").ZodString>;
|
|
118
|
-
}, import("better-auth").$strip>;
|
|
119
|
-
use: ((inputContext: import("better-call").MiddlewareInputContext<import("better-call").MiddlewareOptions>) => Promise<{
|
|
120
|
-
session: {
|
|
121
|
-
session: Record<string, any> & {
|
|
122
|
-
id: string;
|
|
123
|
-
createdAt: Date;
|
|
124
|
-
updatedAt: Date;
|
|
125
|
-
userId: string;
|
|
126
|
-
expiresAt: Date;
|
|
127
|
-
token: string;
|
|
128
|
-
ipAddress?: string | null | undefined;
|
|
129
|
-
userAgent?: string | null | undefined;
|
|
130
|
-
};
|
|
131
|
-
user: Record<string, any> & {
|
|
132
|
-
id: string;
|
|
133
|
-
createdAt: Date;
|
|
134
|
-
updatedAt: Date;
|
|
135
|
-
email: string;
|
|
136
|
-
emailVerified: boolean;
|
|
137
|
-
name: string;
|
|
138
|
-
image?: string | null | undefined;
|
|
139
|
-
};
|
|
140
|
-
};
|
|
141
|
-
}>)[];
|
|
142
|
-
metadata: {
|
|
143
|
-
openapi: {
|
|
144
|
-
description: string;
|
|
145
|
-
responses: {
|
|
146
|
-
"200": {
|
|
147
|
-
description: string;
|
|
148
|
-
content: {
|
|
149
|
-
"application/json": {
|
|
150
|
-
schema: {
|
|
151
|
-
type: "object";
|
|
152
|
-
properties: {
|
|
153
|
-
url: {
|
|
154
|
-
type: string;
|
|
155
|
-
format: string;
|
|
156
|
-
description: string;
|
|
157
|
-
};
|
|
158
|
-
redirect: {
|
|
159
|
-
type: string;
|
|
160
|
-
description: string;
|
|
161
|
-
enum: boolean[];
|
|
162
|
-
};
|
|
163
|
-
};
|
|
164
|
-
required: string[];
|
|
165
|
-
};
|
|
166
|
-
};
|
|
167
|
-
};
|
|
168
|
-
};
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
};
|
|
172
|
-
}, {
|
|
173
|
-
url: string;
|
|
174
|
-
redirect: boolean;
|
|
175
|
-
}>;
|
|
176
|
-
};
|
|
177
|
-
options: import("better-auth/plugins").GenericOAuthOptions;
|
|
35
|
+
}>;
|
|
36
|
+
options: import("better-auth/plugins").GenericOAuthOptions<string>;
|
|
178
37
|
$ERROR_CODES: {
|
|
179
38
|
INVALID_OAUTH_CONFIGURATION: import("better-auth").RawError<"INVALID_OAUTH_CONFIGURATION">;
|
|
180
39
|
TOKEN_URL_NOT_FOUND: import("better-auth").RawError<"TOKEN_URL_NOT_FOUND">;
|
|
181
|
-
PROVIDER_CONFIG_NOT_FOUND: import("better-auth").RawError<"PROVIDER_CONFIG_NOT_FOUND">;
|
|
182
|
-
PROVIDER_ID_REQUIRED: import("better-auth").RawError<"PROVIDER_ID_REQUIRED">;
|
|
183
|
-
INVALID_OAUTH_CONFIG: import("better-auth").RawError<"INVALID_OAUTH_CONFIG">;
|
|
184
|
-
SESSION_REQUIRED: import("better-auth").RawError<"SESSION_REQUIRED">;
|
|
185
|
-
ISSUER_MISMATCH: import("better-auth").RawError<"ISSUER_MISMATCH">;
|
|
186
|
-
ISSUER_MISSING: import("better-auth").RawError<"ISSUER_MISSING">;
|
|
187
40
|
};
|
|
188
41
|
}, {
|
|
189
42
|
id: "next-cookies";
|
|
43
|
+
version: string;
|
|
190
44
|
hooks: {
|
|
191
45
|
before: {
|
|
192
46
|
matcher(ctx: import("better-auth").HookEndpointContext): boolean;
|
|
193
|
-
handler: (inputContext: import("better-
|
|
47
|
+
handler: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>>;
|
|
194
48
|
}[];
|
|
195
49
|
after: {
|
|
196
50
|
matcher(ctx: import("better-auth").HookEndpointContext): true;
|
|
197
|
-
handler: (inputContext: import("better-
|
|
51
|
+
handler: import("better-auth").Middleware<import("better-auth").MiddlewareOptions, (inputContext: import("better-auth").MiddlewareInputContext<import("better-auth").MiddlewareOptions>) => Promise<void>>;
|
|
198
52
|
}[];
|
|
199
53
|
};
|
|
200
54
|
}];
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Auth } from "better-auth";
|
|
2
2
|
import { headers as nextHeaders } from "next/headers";
|
|
3
3
|
import type { NextRequest } from "next/server";
|
|
4
|
-
export declare function getSignOutUrlRoute({ auth, discoveryUrl, federatedLogout,
|
|
4
|
+
export declare function getSignOutUrlRoute({ auth, discoveryUrl, federatedLogout, headers, }: {
|
|
5
5
|
auth: Auth;
|
|
6
6
|
discoveryUrl?: string;
|
|
7
7
|
federatedLogout?: boolean;
|
|
8
|
-
providerId?: string;
|
|
9
8
|
headers: typeof nextHeaders;
|
|
10
9
|
}): (request: NextRequest) => Promise<Response>;
|
package/package.json
CHANGED
|
@@ -1,29 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imtf/auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.0",
|
|
4
4
|
"description": "Better auth wrapper for imtf usage",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"prebuild": "npm run build:clean",
|
|
10
|
-
"build:clean": "rimraf lib",
|
|
11
|
-
"build:js": "vite build",
|
|
12
|
-
"build:types": "tsc --project ./tsconfig.build.json && tsc-alias -p ./tsconfig.build.json",
|
|
13
|
-
"build": "concurrently npm:build:js npm:build:types",
|
|
14
|
-
"lint": "eslint src --cache --report-unused-disable-directives --max-warnings 0",
|
|
15
|
-
"test": "vitest",
|
|
16
|
-
"test:ui": "vitest --ui --coverage",
|
|
17
|
-
"test:coverage": "vitest run --coverage",
|
|
18
|
-
"typecheck": "tsc --noEmit",
|
|
19
|
-
"checks": "concurrently --kill-others-on-fail npm:lint npm:typecheck",
|
|
20
|
-
"prepublishOnly": "npm run build && npm run checks"
|
|
21
|
-
},
|
|
22
8
|
"files": [
|
|
23
9
|
"lib",
|
|
24
10
|
"schemas"
|
|
25
11
|
],
|
|
26
|
-
"prettier": "@imtf/prettier-config",
|
|
27
12
|
"module": "./lib/index.esm.js",
|
|
28
13
|
"types": "./lib/types/index.d.ts",
|
|
29
14
|
"exports": {
|
|
@@ -33,18 +18,34 @@
|
|
|
33
18
|
}
|
|
34
19
|
},
|
|
35
20
|
"dependencies": {
|
|
36
|
-
"@imtf/panache": "^5.
|
|
21
|
+
"@imtf/panache": "^5.10.2"
|
|
37
22
|
},
|
|
38
23
|
"peerDependencies": {
|
|
39
24
|
"@mui/lab": "^7.0.1-beta.18",
|
|
40
25
|
"@mui/material": "^7.1.0",
|
|
41
26
|
"react": "^18.0.0 || ^19.0.0",
|
|
42
27
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
43
|
-
"better-auth": "^1.
|
|
28
|
+
"better-auth": "^1.7.1",
|
|
29
|
+
"zod": "^4.3.6"
|
|
44
30
|
},
|
|
45
31
|
"devDependencies": {
|
|
46
32
|
"@mui/lab": "^7.0.1-beta.18",
|
|
47
33
|
"@mui/material": "^7.1.0",
|
|
48
|
-
"better-auth": "^1.
|
|
34
|
+
"better-auth": "^1.7.1",
|
|
35
|
+
"zod": "^4.3.6"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"prebuild": "pnpm run build:clean",
|
|
39
|
+
"build:clean": "rimraf lib",
|
|
40
|
+
"build:js": "vite build",
|
|
41
|
+
"build:types": "tsc --project ./tsconfig.build.json && tsc-alias -p ./tsconfig.build.json",
|
|
42
|
+
"build": "concurrently pnpm:build:js pnpm:build:types",
|
|
43
|
+
"lint": "oxlint --type-aware --type-check --deny-warnings src",
|
|
44
|
+
"format:check": "oxfmt --check './src/**/*.{ts,tsx}'",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"test": "vitest",
|
|
47
|
+
"test:ui": "vitest --ui --coverage",
|
|
48
|
+
"test:coverage": "vitest run --coverage",
|
|
49
|
+
"checks": "concurrently --kill-others-on-fail pnpm:lint pnpm:typecheck pnpm:format:check"
|
|
49
50
|
}
|
|
50
|
-
}
|
|
51
|
+
}
|