@object-ui/auth 3.1.2 → 3.1.3
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 +2 -3
- package/dist/createAuthClient.d.ts +5 -4
- package/dist/createAuthClient.d.ts.map +1 -1
- package/dist/createAuthClient.js +95 -53
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Authentication system for Object UI — AuthProvider, guards, login/register for
|
|
|
8
8
|
- 🛡️ **AuthGuard** - Protect routes and components from unauthenticated access
|
|
9
9
|
- 📝 **Pre-built Forms** - LoginForm, RegisterForm, and ForgotPasswordForm ready to use
|
|
10
10
|
- 👤 **UserMenu** - Display authenticated user info with sign-out support
|
|
11
|
-
- 🔑 **Auth Client Factory** - `createAuthClient`
|
|
11
|
+
- 🔑 **Auth Client Factory** - `createAuthClient` powered by official [better-auth](https://better-auth.com) client
|
|
12
12
|
- 🌐 **Authenticated Fetch** - `createAuthenticatedFetch` for automatic token injection
|
|
13
13
|
- 👀 **Preview Mode** - Auto-login with simulated identity for marketplace demos and app showcases
|
|
14
14
|
- 🎯 **Type-Safe** - Full TypeScript support with exported types
|
|
@@ -30,8 +30,7 @@ import { AuthProvider, useAuth, AuthGuard } from '@object-ui/auth';
|
|
|
30
30
|
import { createAuthClient } from '@object-ui/auth';
|
|
31
31
|
|
|
32
32
|
const authClient = createAuthClient({
|
|
33
|
-
|
|
34
|
-
apiUrl: 'https://api.example.com/auth',
|
|
33
|
+
baseURL: 'https://api.example.com/auth',
|
|
35
34
|
});
|
|
36
35
|
|
|
37
36
|
function App() {
|
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { AuthClient, AuthClientConfig } from './types';
|
|
9
9
|
/**
|
|
10
|
-
* Create an auth client instance.
|
|
10
|
+
* Create an auth client instance backed by the official better-auth client.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* Internally delegates to `createAuthClient` from `better-auth/client`,
|
|
13
|
+
* exposing the same {@link AuthClient} interface so that AuthProvider,
|
|
14
|
+
* createAuthenticatedFetch, and all downstream consumers continue to work
|
|
15
|
+
* without changes.
|
|
15
16
|
*
|
|
16
17
|
* @example
|
|
17
18
|
* ```ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAwD,MAAM,SAAS,CAAC;AAiClH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CAwFrE"}
|
package/dist/createAuthClient.js
CHANGED
|
@@ -5,12 +5,45 @@
|
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
|
+
import { createAuthClient as createBetterAuthClient } from 'better-auth/client';
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
+
* Resolve a baseURL (which may be relative or absolute) into the
|
|
11
|
+
* `{ origin, basePath }` pair required by the better-auth client.
|
|
10
12
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* - Absolute URLs (e.g. `http://localhost:3000/api/auth`) are split into origin + pathname.
|
|
14
|
+
* - Relative paths (e.g. `/api/v1/auth`) use `window.location.origin` in
|
|
15
|
+
* browser environments, falling back to `http://localhost` elsewhere.
|
|
16
|
+
*/
|
|
17
|
+
function resolveAuthURL(baseURL) {
|
|
18
|
+
try {
|
|
19
|
+
const url = new URL(baseURL);
|
|
20
|
+
return { origin: url.origin, basePath: url.pathname.replace(/\/$/, '') };
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Relative URL – resolve against the current origin when available
|
|
24
|
+
const origin = getWindowOrigin() ?? 'http://localhost';
|
|
25
|
+
return { origin, basePath: baseURL.replace(/\/$/, '') };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Safely read window.location.origin when available (browser environments). */
|
|
29
|
+
function getWindowOrigin() {
|
|
30
|
+
try {
|
|
31
|
+
if (typeof window !== 'undefined' && window.location?.origin) {
|
|
32
|
+
return window.location.origin;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// window may be defined but accessing location can throw in some SSR environments
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create an auth client instance backed by the official better-auth client.
|
|
42
|
+
*
|
|
43
|
+
* Internally delegates to `createAuthClient` from `better-auth/client`,
|
|
44
|
+
* exposing the same {@link AuthClient} interface so that AuthProvider,
|
|
45
|
+
* createAuthenticatedFetch, and all downstream consumers continue to work
|
|
46
|
+
* without changes.
|
|
14
47
|
*
|
|
15
48
|
* @example
|
|
16
49
|
* ```ts
|
|
@@ -19,70 +52,79 @@
|
|
|
19
52
|
* ```
|
|
20
53
|
*/
|
|
21
54
|
export function createAuthClient(config) {
|
|
22
|
-
const { baseURL, fetchFn
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const body = await response.json().catch(() => null);
|
|
35
|
-
const message = (body && typeof body === 'object' && 'message' in body)
|
|
36
|
-
? String(body.message)
|
|
37
|
-
: `Auth request failed with status ${response.status}`;
|
|
38
|
-
throw new Error(message);
|
|
39
|
-
}
|
|
40
|
-
return response.json();
|
|
41
|
-
}
|
|
55
|
+
const { baseURL, fetchFn } = config;
|
|
56
|
+
const { origin, basePath } = resolveAuthURL(baseURL);
|
|
57
|
+
const betterAuth = createBetterAuthClient({
|
|
58
|
+
baseURL: origin,
|
|
59
|
+
basePath,
|
|
60
|
+
disableDefaultFetchPlugins: true,
|
|
61
|
+
fetchOptions: fetchFn ? { customFetchImpl: fetchFn } : undefined,
|
|
62
|
+
});
|
|
63
|
+
// The better-auth client exposes methods whose TS return types are narrower
|
|
64
|
+
// than the runtime JSON the server actually sends (e.g. `session` on signIn).
|
|
65
|
+
// We deliberately cast through `unknown` to bridge from better-auth types
|
|
66
|
+
// to the ObjectUI AuthClient contract.
|
|
42
67
|
return {
|
|
43
68
|
async signIn(credentials) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
69
|
+
const { data, error } = await betterAuth.signIn.email({
|
|
70
|
+
email: credentials.email,
|
|
71
|
+
password: credentials.password,
|
|
47
72
|
});
|
|
73
|
+
if (error) {
|
|
74
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
75
|
+
}
|
|
76
|
+
const payload = data;
|
|
77
|
+
return { user: payload.user, session: payload.session };
|
|
48
78
|
},
|
|
49
|
-
async signUp(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
79
|
+
async signUp(signUpData) {
|
|
80
|
+
const { data, error } = await betterAuth.signUp.email({
|
|
81
|
+
email: signUpData.email,
|
|
82
|
+
password: signUpData.password,
|
|
83
|
+
name: signUpData.name,
|
|
53
84
|
});
|
|
85
|
+
if (error) {
|
|
86
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
87
|
+
}
|
|
88
|
+
const payload = data;
|
|
89
|
+
return { user: payload.user, session: payload.session };
|
|
54
90
|
},
|
|
55
91
|
async signOut() {
|
|
56
|
-
|
|
92
|
+
const { error } = await betterAuth.signOut();
|
|
93
|
+
if (error) {
|
|
94
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
95
|
+
}
|
|
57
96
|
},
|
|
58
97
|
async getSession() {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
method: 'GET',
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
catch {
|
|
98
|
+
const { data, error } = await betterAuth.getSession();
|
|
99
|
+
if (error || !data)
|
|
65
100
|
return null;
|
|
66
|
-
|
|
101
|
+
const payload = data;
|
|
102
|
+
return { user: payload.user, session: payload.session };
|
|
67
103
|
},
|
|
68
104
|
async forgotPassword(email) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
105
|
+
const forgetPw = betterAuth.forgetPassword;
|
|
106
|
+
const { error } = await forgetPw({ email, redirectTo: '/' });
|
|
107
|
+
if (error) {
|
|
108
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
109
|
+
}
|
|
73
110
|
},
|
|
74
111
|
async resetPassword(token, newPassword) {
|
|
75
|
-
await
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
112
|
+
const { error } = await betterAuth.resetPassword({ token, newPassword });
|
|
113
|
+
if (error) {
|
|
114
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
115
|
+
}
|
|
79
116
|
},
|
|
80
|
-
async updateUser(
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
117
|
+
async updateUser(userData) {
|
|
118
|
+
const { data, error } = await betterAuth.updateUser(userData);
|
|
119
|
+
if (error) {
|
|
120
|
+
throw new Error(error.message ?? `Auth request failed with status ${error.status}`);
|
|
121
|
+
}
|
|
122
|
+
if (!data) {
|
|
123
|
+
throw new Error('Update user returned no data');
|
|
124
|
+
}
|
|
125
|
+
// The server response may wrap the user in a `user` key or return it directly
|
|
126
|
+
const raw = data;
|
|
127
|
+
return (raw && typeof raw === 'object' && 'user' in raw ? raw.user : raw);
|
|
86
128
|
},
|
|
87
129
|
};
|
|
88
130
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/auth",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Authentication system for Object UI with AuthProvider, useAuth hook, AuthGuard, and form components.",
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"react": "^18.0.0 || ^19.0.0"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"
|
|
30
|
+
"better-auth": "^1.5.4",
|
|
31
|
+
"@object-ui/types": "3.1.3"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/react": "19.2.14",
|