@object-ui/auth 0.1.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ObjectQL
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.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { AuthUser, AuthSession } from './types';
9
+ export interface AuthContextValue {
10
+ /** Current authenticated user */
11
+ user: AuthUser | null;
12
+ /** Current session information */
13
+ session: AuthSession | null;
14
+ /** Whether the user is authenticated */
15
+ isAuthenticated: boolean;
16
+ /** Whether auth state is loading */
17
+ isLoading: boolean;
18
+ /** Authentication error */
19
+ error: Error | null;
20
+ /** Sign in with email and password */
21
+ signIn: (email: string, password: string) => Promise<void>;
22
+ /** Sign up with name, email, and password */
23
+ signUp: (name: string, email: string, password: string) => Promise<void>;
24
+ /** Sign out the current user */
25
+ signOut: () => Promise<void>;
26
+ /** Update user profile */
27
+ updateUser: (data: Partial<AuthUser>) => Promise<void>;
28
+ /** Request password reset */
29
+ forgotPassword: (email: string) => Promise<void>;
30
+ /** Reset password with token */
31
+ resetPassword: (token: string, newPassword: string) => Promise<void>;
32
+ }
33
+ export declare const AuthCtx: import("react").Context<AuthContextValue | null>;
34
+ //# sourceMappingURL=AuthContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../src/AuthContext.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,kCAAkC;IAClC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,wCAAwC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,oCAAoC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,sCAAsC;IACtC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,6CAA6C;IAC7C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0BAA0B;IAC1B,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,6BAA6B;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,gCAAgC;IAChC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtE;AAED,eAAO,MAAM,OAAO,kDAA+C,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { createContext } from 'react';
9
+ export const AuthCtx = createContext(null);
10
+ AuthCtx.displayName = 'AuthContext';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import React from 'react';
9
+ export interface AuthGuardProps {
10
+ /** Content to render when user is not authenticated */
11
+ fallback?: React.ReactNode;
12
+ /** Required roles (user must have at least one) */
13
+ requiredRoles?: string[];
14
+ /** Required permissions (user must have all) */
15
+ requiredPermissions?: string[];
16
+ /** Content to render when loading */
17
+ loadingFallback?: React.ReactNode;
18
+ /** Children to render when authenticated */
19
+ children: React.ReactNode;
20
+ }
21
+ /**
22
+ * Route guard component that conditionally renders children
23
+ * based on authentication and authorization state.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * <AuthGuard fallback={<Navigate to="/login" />}>
28
+ * <ProtectedPage />
29
+ * </AuthGuard>
30
+ *
31
+ * <AuthGuard requiredRoles={['admin']} fallback={<AccessDenied />}>
32
+ * <AdminPanel />
33
+ * </AuthGuard>
34
+ * ```
35
+ */
36
+ export declare function AuthGuard({ fallback, requiredRoles, loadingFallback, children, }: AuthGuardProps): import("react/jsx-runtime").JSX.Element;
37
+ //# sourceMappingURL=AuthGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthGuard.d.ts","sourceRoot":"","sources":["../src/AuthGuard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,gDAAgD;IAChD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,qCAAqC;IACrC,eAAe,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAClC,4CAA4C;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAe,EACf,aAAa,EACb,eAAe,EACf,QAAQ,GACT,EAAE,cAAc,2CAqBhB"}
@@ -0,0 +1,35 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { useAuth } from './useAuth';
3
+ /**
4
+ * Route guard component that conditionally renders children
5
+ * based on authentication and authorization state.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <AuthGuard fallback={<Navigate to="/login" />}>
10
+ * <ProtectedPage />
11
+ * </AuthGuard>
12
+ *
13
+ * <AuthGuard requiredRoles={['admin']} fallback={<AccessDenied />}>
14
+ * <AdminPanel />
15
+ * </AuthGuard>
16
+ * ```
17
+ */
18
+ export function AuthGuard({ fallback = null, requiredRoles, loadingFallback, children, }) {
19
+ const { isAuthenticated, isLoading, user } = useAuth();
20
+ if (isLoading) {
21
+ return _jsx(_Fragment, { children: loadingFallback ?? null });
22
+ }
23
+ if (!isAuthenticated) {
24
+ return _jsx(_Fragment, { children: fallback });
25
+ }
26
+ // Check role requirements
27
+ if (requiredRoles && requiredRoles.length > 0 && user) {
28
+ const userRoles = user.roles ?? (user.role ? [user.role] : []);
29
+ const hasRole = requiredRoles.some((role) => userRoles.includes(role));
30
+ if (!hasRole) {
31
+ return _jsx(_Fragment, { children: fallback });
32
+ }
33
+ }
34
+ return _jsx(_Fragment, { children: children });
35
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import React from 'react';
9
+ import type { AuthProviderConfig } from './types';
10
+ export interface AuthProviderProps extends AuthProviderConfig {
11
+ children: React.ReactNode;
12
+ }
13
+ /**
14
+ * Authentication context provider.
15
+ *
16
+ * Wraps the application to provide authentication state and methods
17
+ * to all child components via the useAuth hook.
18
+ *
19
+ * @example
20
+ * ```tsx
21
+ * <AuthProvider authUrl="/api/auth">
22
+ * <App />
23
+ * </AuthProvider>
24
+ * ```
25
+ */
26
+ export declare function AuthProvider({ authUrl, client: externalClient, onAuthStateChange, children, }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
27
+ //# sourceMappingURL=AuthProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthProvider.d.ts","sourceRoot":"","sources":["../src/AuthProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AACzE,OAAO,KAAK,EAAwB,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAIxE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,MAAM,EAAE,cAAc,EACtB,iBAAiB,EACjB,QAAQ,GACT,EAAE,iBAAiB,2CAmKnB"}
@@ -0,0 +1,166 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { useState, useEffect, useCallback, useMemo } from 'react';
10
+ import { AuthCtx } from './AuthContext';
11
+ import { createAuthClient } from './createAuthClient';
12
+ /**
13
+ * Authentication context provider.
14
+ *
15
+ * Wraps the application to provide authentication state and methods
16
+ * to all child components via the useAuth hook.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * <AuthProvider authUrl="/api/auth">
21
+ * <App />
22
+ * </AuthProvider>
23
+ * ```
24
+ */
25
+ export function AuthProvider({ authUrl, client: externalClient, onAuthStateChange, children, }) {
26
+ const client = useMemo(() => externalClient ?? createAuthClient({ baseURL: authUrl }), [externalClient, authUrl]);
27
+ const [user, setUser] = useState(null);
28
+ const [session, setSession] = useState(null);
29
+ const [isLoading, setIsLoading] = useState(true);
30
+ const [error, setError] = useState(null);
31
+ const isAuthenticated = user !== null && session !== null;
32
+ // Load session on mount
33
+ useEffect(() => {
34
+ let cancelled = false;
35
+ async function loadSession() {
36
+ try {
37
+ const result = await client.getSession();
38
+ if (cancelled)
39
+ return;
40
+ if (result) {
41
+ setUser(result.user);
42
+ setSession(result.session);
43
+ }
44
+ }
45
+ catch (err) {
46
+ if (cancelled)
47
+ return;
48
+ setError(err instanceof Error ? err : new Error(String(err)));
49
+ }
50
+ finally {
51
+ if (!cancelled) {
52
+ setIsLoading(false);
53
+ }
54
+ }
55
+ }
56
+ loadSession();
57
+ return () => { cancelled = true; };
58
+ }, [client]);
59
+ // Notify on auth state changes
60
+ useEffect(() => {
61
+ onAuthStateChange?.({
62
+ user,
63
+ session,
64
+ isAuthenticated,
65
+ isLoading,
66
+ error,
67
+ });
68
+ }, [user, session, isAuthenticated, isLoading, error, onAuthStateChange]);
69
+ const signIn = useCallback(async (email, password) => {
70
+ setIsLoading(true);
71
+ setError(null);
72
+ try {
73
+ const result = await client.signIn({ email, password });
74
+ setUser(result.user);
75
+ setSession(result.session);
76
+ }
77
+ catch (err) {
78
+ const authError = err instanceof Error ? err : new Error(String(err));
79
+ setError(authError);
80
+ throw authError;
81
+ }
82
+ finally {
83
+ setIsLoading(false);
84
+ }
85
+ }, [client]);
86
+ const signUp = useCallback(async (name, email, password) => {
87
+ setIsLoading(true);
88
+ setError(null);
89
+ try {
90
+ const result = await client.signUp({ name, email, password });
91
+ setUser(result.user);
92
+ setSession(result.session);
93
+ }
94
+ catch (err) {
95
+ const authError = err instanceof Error ? err : new Error(String(err));
96
+ setError(authError);
97
+ throw authError;
98
+ }
99
+ finally {
100
+ setIsLoading(false);
101
+ }
102
+ }, [client]);
103
+ const signOut = useCallback(async () => {
104
+ setIsLoading(true);
105
+ try {
106
+ await client.signOut();
107
+ setUser(null);
108
+ setSession(null);
109
+ setError(null);
110
+ }
111
+ catch (err) {
112
+ setError(err instanceof Error ? err : new Error(String(err)));
113
+ }
114
+ finally {
115
+ setIsLoading(false);
116
+ }
117
+ }, [client]);
118
+ const updateUser = useCallback(async (data) => {
119
+ setError(null);
120
+ try {
121
+ const updated = await client.updateUser(data);
122
+ setUser(updated);
123
+ }
124
+ catch (err) {
125
+ const authError = err instanceof Error ? err : new Error(String(err));
126
+ setError(authError);
127
+ throw authError;
128
+ }
129
+ }, [client]);
130
+ const forgotPassword = useCallback(async (email) => {
131
+ setError(null);
132
+ try {
133
+ await client.forgotPassword(email);
134
+ }
135
+ catch (err) {
136
+ const authError = err instanceof Error ? err : new Error(String(err));
137
+ setError(authError);
138
+ throw authError;
139
+ }
140
+ }, [client]);
141
+ const resetPassword = useCallback(async (token, newPassword) => {
142
+ setError(null);
143
+ try {
144
+ await client.resetPassword(token, newPassword);
145
+ }
146
+ catch (err) {
147
+ const authError = err instanceof Error ? err : new Error(String(err));
148
+ setError(authError);
149
+ throw authError;
150
+ }
151
+ }, [client]);
152
+ const value = useMemo(() => ({
153
+ user,
154
+ session,
155
+ isAuthenticated,
156
+ isLoading,
157
+ error,
158
+ signIn,
159
+ signUp,
160
+ signOut,
161
+ updateUser,
162
+ forgotPassword,
163
+ resetPassword,
164
+ }), [user, session, isAuthenticated, isLoading, error, signIn, signUp, signOut, updateUser, forgotPassword, resetPassword]);
165
+ return _jsx(AuthCtx.Provider, { value: value, children: children });
166
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export interface ForgotPasswordFormProps {
9
+ /** Callback on successful submission */
10
+ onSuccess?: () => void;
11
+ /** Callback on error */
12
+ onError?: (error: Error) => void;
13
+ /** Link to login page */
14
+ loginUrl?: string;
15
+ /** Custom title */
16
+ title?: string;
17
+ /** Custom description */
18
+ description?: string;
19
+ }
20
+ /**
21
+ * Forgot password form component.
22
+ * Sends a password reset email to the user.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <ForgotPasswordForm
27
+ * onSuccess={() => setShowSuccess(true)}
28
+ * loginUrl="/login"
29
+ * />
30
+ * ```
31
+ */
32
+ export declare function ForgotPasswordForm({ onSuccess, onError, loginUrl, title, description, }: ForgotPasswordFormProps): import("react/jsx-runtime").JSX.Element;
33
+ //# sourceMappingURL=ForgotPasswordForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ForgotPasswordForm.d.ts","sourceRoot":"","sources":["../src/ForgotPasswordForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,wBAAwB;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,SAAS,EACT,OAAO,EACP,QAAmB,EACnB,KAA6B,EAC7B,WAA0F,GAC3F,EAAE,uBAAuB,2CA4FzB"}
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { useState } from 'react';
10
+ import { useAuth } from './useAuth';
11
+ /**
12
+ * Forgot password form component.
13
+ * Sends a password reset email to the user.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <ForgotPasswordForm
18
+ * onSuccess={() => setShowSuccess(true)}
19
+ * loginUrl="/login"
20
+ * />
21
+ * ```
22
+ */
23
+ export function ForgotPasswordForm({ onSuccess, onError, loginUrl = '/login', title = 'Reset your password', description = 'Enter your email address and we\'ll send you a link to reset your password', }) {
24
+ const { forgotPassword, isLoading } = useAuth();
25
+ const [email, setEmail] = useState('');
26
+ const [error, setError] = useState(null);
27
+ const [submitted, setSubmitted] = useState(false);
28
+ const handleSubmit = async (e) => {
29
+ e.preventDefault();
30
+ setError(null);
31
+ try {
32
+ await forgotPassword(email);
33
+ setSubmitted(true);
34
+ onSuccess?.();
35
+ }
36
+ catch (err) {
37
+ const authError = err instanceof Error ? err : new Error(String(err));
38
+ setError(authError.message);
39
+ onError?.(authError);
40
+ }
41
+ };
42
+ if (submitted) {
43
+ return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]", children: [_jsxs("div", { className: "flex flex-col space-y-2 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: "Check your email" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["We've sent a password reset link to ", _jsx("strong", { children: email }), ". Please check your inbox and follow the instructions."] })] }), loginUrl && (_jsx("p", { className: "px-8 text-center text-sm text-muted-foreground", children: _jsx("a", { href: loginUrl, className: "text-primary underline-offset-4 hover:underline", children: "Back to sign in" }) }))] }));
44
+ }
45
+ return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]", children: [_jsxs("div", { className: "flex flex-col space-y-2 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "rounded-md bg-destructive/15 p-3 text-sm text-destructive", role: "alert", children: error })), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "forgot-email", className: "text-sm font-medium leading-none", children: "Email" }), _jsx("input", { id: "forgot-email", type: "email", placeholder: "name@example.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, autoComplete: "email", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsx("button", { type: "submit", disabled: isLoading, className: "inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground ring-offset-background transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", children: isLoading ? 'Sending...' : 'Send Reset Link' })] }), loginUrl && (_jsxs("p", { className: "px-8 text-center text-sm text-muted-foreground", children: ["Remember your password?", ' ', _jsx("a", { href: loginUrl, className: "text-primary underline-offset-4 hover:underline", children: "Sign in" })] }))] }));
46
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export interface LoginFormProps {
9
+ /** Callback on successful login */
10
+ onSuccess?: () => void;
11
+ /** Callback on login error */
12
+ onError?: (error: Error) => void;
13
+ /** Link to registration page */
14
+ registerUrl?: string;
15
+ /** Link to forgot password page */
16
+ forgotPasswordUrl?: string;
17
+ /** Custom title */
18
+ title?: string;
19
+ /** Custom description */
20
+ description?: string;
21
+ }
22
+ /**
23
+ * Login form component with email/password authentication.
24
+ * Uses Tailwind CSS utility classes for styling.
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * <LoginForm
29
+ * onSuccess={() => navigate('/dashboard')}
30
+ * registerUrl="/register"
31
+ * forgotPasswordUrl="/forgot-password"
32
+ * />
33
+ * ```
34
+ */
35
+ export declare function LoginForm({ onSuccess, onError, registerUrl, forgotPasswordUrl, title, description, }: LoginFormProps): import("react/jsx-runtime").JSX.Element;
36
+ //# sourceMappingURL=LoginForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../src/LoginForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,gCAAgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,OAAO,EACP,WAAyB,EACzB,iBAAsC,EACtC,KAAiC,EACjC,WAAyD,GAC1D,EAAE,cAAc,2CAiGhB"}
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { useState } from 'react';
10
+ import { useAuth } from './useAuth';
11
+ /**
12
+ * Login form component with email/password authentication.
13
+ * Uses Tailwind CSS utility classes for styling.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <LoginForm
18
+ * onSuccess={() => navigate('/dashboard')}
19
+ * registerUrl="/register"
20
+ * forgotPasswordUrl="/forgot-password"
21
+ * />
22
+ * ```
23
+ */
24
+ export function LoginForm({ onSuccess, onError, registerUrl = '/register', forgotPasswordUrl = '/forgot-password', title = 'Sign in to your account', description = 'Enter your email and password to continue', }) {
25
+ const { signIn, isLoading } = useAuth();
26
+ const [email, setEmail] = useState('');
27
+ const [password, setPassword] = useState('');
28
+ const [error, setError] = useState(null);
29
+ const handleSubmit = async (e) => {
30
+ e.preventDefault();
31
+ setError(null);
32
+ try {
33
+ await signIn(email, password);
34
+ onSuccess?.();
35
+ }
36
+ catch (err) {
37
+ const authError = err instanceof Error ? err : new Error(String(err));
38
+ setError(authError.message);
39
+ onError?.(authError);
40
+ }
41
+ };
42
+ return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]", children: [_jsxs("div", { className: "flex flex-col space-y-2 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "rounded-md bg-destructive/15 p-3 text-sm text-destructive", role: "alert", children: error })), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "login-email", className: "text-sm font-medium leading-none", children: "Email" }), _jsx("input", { id: "login-email", type: "email", placeholder: "name@example.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, autoComplete: "email", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("label", { htmlFor: "login-password", className: "text-sm font-medium leading-none", children: "Password" }), forgotPasswordUrl && (_jsx("a", { href: forgotPasswordUrl, className: "text-sm text-primary underline-offset-4 hover:underline", children: "Forgot password?" }))] }), _jsx("input", { id: "login-password", type: "password", placeholder: "Enter your password", value: password, onChange: (e) => setPassword(e.target.value), required: true, autoComplete: "current-password", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsx("button", { type: "submit", disabled: isLoading, className: "inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground ring-offset-background transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", children: isLoading ? 'Signing in...' : 'Sign In' })] }), registerUrl && (_jsxs("p", { className: "px-8 text-center text-sm text-muted-foreground", children: ["Don't have an account?", ' ', _jsx("a", { href: registerUrl, className: "text-primary underline-offset-4 hover:underline", children: "Sign up" })] }))] }));
43
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export interface RegisterFormProps {
9
+ /** Callback on successful registration */
10
+ onSuccess?: () => void;
11
+ /** Callback on registration error */
12
+ onError?: (error: Error) => void;
13
+ /** Link to login page */
14
+ loginUrl?: string;
15
+ /** Custom title */
16
+ title?: string;
17
+ /** Custom description */
18
+ description?: string;
19
+ }
20
+ /**
21
+ * Registration form component with name, email, and password fields.
22
+ * Uses Tailwind CSS utility classes for styling.
23
+ *
24
+ * @example
25
+ * ```tsx
26
+ * <RegisterForm
27
+ * onSuccess={() => navigate('/dashboard')}
28
+ * loginUrl="/login"
29
+ * />
30
+ * ```
31
+ */
32
+ export declare function RegisterForm({ onSuccess, onError, loginUrl, title, description, }: RegisterFormProps): import("react/jsx-runtime").JSX.Element;
33
+ //# sourceMappingURL=RegisterForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegisterForm.d.ts","sourceRoot":"","sources":["../src/RegisterForm.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,qCAAqC;IACrC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,OAAO,EACP,QAAmB,EACnB,KAA2B,EAC3B,WAAqD,GACtD,EAAE,iBAAiB,2CAuInB"}
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * ObjectUI
4
+ * Copyright (c) 2024-present ObjectStack Inc.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+ import { useState } from 'react';
10
+ import { useAuth } from './useAuth';
11
+ /**
12
+ * Registration form component with name, email, and password fields.
13
+ * Uses Tailwind CSS utility classes for styling.
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * <RegisterForm
18
+ * onSuccess={() => navigate('/dashboard')}
19
+ * loginUrl="/login"
20
+ * />
21
+ * ```
22
+ */
23
+ export function RegisterForm({ onSuccess, onError, loginUrl = '/login', title = 'Create an account', description = 'Enter your information to get started', }) {
24
+ const { signUp, isLoading } = useAuth();
25
+ const [name, setName] = useState('');
26
+ const [email, setEmail] = useState('');
27
+ const [password, setPassword] = useState('');
28
+ const [confirmPassword, setConfirmPassword] = useState('');
29
+ const [error, setError] = useState(null);
30
+ const handleSubmit = async (e) => {
31
+ e.preventDefault();
32
+ setError(null);
33
+ if (password !== confirmPassword) {
34
+ setError('Passwords do not match');
35
+ return;
36
+ }
37
+ if (password.length < 8) {
38
+ setError('Password must be at least 8 characters');
39
+ return;
40
+ }
41
+ try {
42
+ await signUp(name, email, password);
43
+ onSuccess?.();
44
+ }
45
+ catch (err) {
46
+ const authError = err instanceof Error ? err : new Error(String(err));
47
+ setError(authError.message);
48
+ onError?.(authError);
49
+ }
50
+ };
51
+ return (_jsxs("div", { className: "mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]", children: [_jsxs("div", { className: "flex flex-col space-y-2 text-center", children: [_jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: title }), _jsx("p", { className: "text-sm text-muted-foreground", children: description })] }), _jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [error && (_jsx("div", { className: "rounded-md bg-destructive/15 p-3 text-sm text-destructive", role: "alert", children: error })), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "register-name", className: "text-sm font-medium leading-none", children: "Name" }), _jsx("input", { id: "register-name", type: "text", placeholder: "John Doe", value: name, onChange: (e) => setName(e.target.value), required: true, autoComplete: "name", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "register-email", className: "text-sm font-medium leading-none", children: "Email" }), _jsx("input", { id: "register-email", type: "email", placeholder: "name@example.com", value: email, onChange: (e) => setEmail(e.target.value), required: true, autoComplete: "email", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "register-password", className: "text-sm font-medium leading-none", children: "Password" }), _jsx("input", { id: "register-password", type: "password", placeholder: "Create a password (min. 8 characters)", value: password, onChange: (e) => setPassword(e.target.value), required: true, minLength: 8, autoComplete: "new-password", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { htmlFor: "register-confirm-password", className: "text-sm font-medium leading-none", children: "Confirm Password" }), _jsx("input", { id: "register-confirm-password", type: "password", placeholder: "Confirm your password", value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), required: true, minLength: 8, autoComplete: "new-password", disabled: isLoading, className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" })] }), _jsx("button", { type: "submit", disabled: isLoading, className: "inline-flex h-10 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground ring-offset-background transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", children: isLoading ? 'Creating account...' : 'Create Account' })] }), loginUrl && (_jsxs("p", { className: "px-8 text-center text-sm text-muted-foreground", children: ["Already have an account?", ' ', _jsx("a", { href: loginUrl, className: "text-primary underline-offset-4 hover:underline", children: "Sign in" })] }))] }));
52
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import React from 'react';
9
+ export interface UserMenuProps {
10
+ /** Custom avatar URL override */
11
+ avatarUrl?: string;
12
+ /** Callback for profile navigation */
13
+ onProfile?: () => void;
14
+ /** Callback for settings navigation */
15
+ onSettings?: () => void;
16
+ /** Custom menu items */
17
+ children?: React.ReactNode;
18
+ }
19
+ /**
20
+ * User menu component displaying the authenticated user's info.
21
+ * Shows avatar, name, email, and common actions (profile, settings, sign out).
22
+ *
23
+ * This is a headless component that provides the user data and actions.
24
+ * The actual dropdown rendering is handled by the consumer (e.g., AppSidebar).
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * <UserMenu onProfile={() => navigate('/profile')} />
29
+ * ```
30
+ */
31
+ export declare function UserMenu({ avatarUrl, onProfile, onSettings, }: UserMenuProps): import("react/jsx-runtime").JSX.Element | null;
32
+ //# sourceMappingURL=UserMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserMenu.d.ts","sourceRoot":"","sources":["../src/UserMenu.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,EACvB,SAAS,EACT,SAAS,EACT,UAAU,GACX,EAAE,aAAa,kDAiEf"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useAuth } from './useAuth';
3
+ import { getUserInitials } from './types';
4
+ /**
5
+ * User menu component displaying the authenticated user's info.
6
+ * Shows avatar, name, email, and common actions (profile, settings, sign out).
7
+ *
8
+ * This is a headless component that provides the user data and actions.
9
+ * The actual dropdown rendering is handled by the consumer (e.g., AppSidebar).
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <UserMenu onProfile={() => navigate('/profile')} />
14
+ * ```
15
+ */
16
+ export function UserMenu({ avatarUrl, onProfile, onSettings, }) {
17
+ const { user, signOut, isAuthenticated } = useAuth();
18
+ if (!isAuthenticated || !user) {
19
+ return null;
20
+ }
21
+ const initials = getUserInitials(user);
22
+ const imageUrl = avatarUrl ?? user.image;
23
+ return (_jsxs("div", { className: "flex items-center gap-2 text-left text-sm", children: [_jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary text-primary-foreground overflow-hidden", children: imageUrl ? (_jsx("img", { src: imageUrl, alt: user.name, className: "h-full w-full object-cover" })) : (_jsx("span", { className: "text-xs font-medium", children: initials })) }), _jsxs("div", { className: "grid flex-1 leading-tight", children: [_jsx("span", { className: "truncate font-semibold", children: user.name }), _jsx("span", { className: "truncate text-xs text-muted-foreground", children: user.email })] }), (onProfile || onSettings) && (_jsxs("div", { className: "flex items-center gap-1", children: [onProfile && (_jsx("button", { type: "button", onClick: onProfile, className: "rounded-md p-1 text-muted-foreground hover:text-foreground", "aria-label": "Profile", children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" }) }) })), onSettings && (_jsx("button", { type: "button", onClick: onSettings, className: "rounded-md p-1 text-muted-foreground hover:text-foreground", "aria-label": "Settings", children: _jsxs("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.066 2.573c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.573 1.066c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.066-2.573c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })] }) }))] })), _jsx("button", { type: "button", onClick: () => signOut(), className: "rounded-md p-1 text-muted-foreground hover:text-destructive", "aria-label": "Sign out", children: _jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" }) }) })] }));
24
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { AuthClient, AuthClientConfig } from './types';
9
+ /**
10
+ * Create an auth client instance.
11
+ *
12
+ * This factory creates an abstraction layer over the authentication provider.
13
+ * It is designed to work with better-auth but can be adapted to any auth backend
14
+ * that exposes standard REST endpoints for sign-in, sign-up, sign-out, and session management.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * const authClient = createAuthClient({ baseURL: '/api/auth' });
19
+ * const { user, session } = await authClient.signIn({ email, password });
20
+ * ```
21
+ */
22
+ export declare function createAuthClient(config: AuthClientConfig): AuthClient;
23
+ //# sourceMappingURL=createAuthClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAuthClient.d.ts","sourceRoot":"","sources":["../src/createAuthClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAwD,MAAM,SAAS,CAAC;AAElH;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,UAAU,CA4ErE"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Create an auth client instance.
10
+ *
11
+ * This factory creates an abstraction layer over the authentication provider.
12
+ * It is designed to work with better-auth but can be adapted to any auth backend
13
+ * that exposes standard REST endpoints for sign-in, sign-up, sign-out, and session management.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const authClient = createAuthClient({ baseURL: '/api/auth' });
18
+ * const { user, session } = await authClient.signIn({ email, password });
19
+ * ```
20
+ */
21
+ export function createAuthClient(config) {
22
+ const { baseURL, fetchFn = fetch } = config;
23
+ async function request(path, options) {
24
+ const url = `${baseURL}${path}`;
25
+ const response = await fetchFn(url, {
26
+ ...options,
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ ...options?.headers,
30
+ },
31
+ credentials: 'include',
32
+ });
33
+ if (!response.ok) {
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
+ }
42
+ return {
43
+ async signIn(credentials) {
44
+ return request('/sign-in/email', {
45
+ method: 'POST',
46
+ body: JSON.stringify(credentials),
47
+ });
48
+ },
49
+ async signUp(data) {
50
+ return request('/sign-up/email', {
51
+ method: 'POST',
52
+ body: JSON.stringify(data),
53
+ });
54
+ },
55
+ async signOut() {
56
+ await request('/sign-out', { method: 'POST' });
57
+ },
58
+ async getSession() {
59
+ try {
60
+ return await request('/get-session', {
61
+ method: 'GET',
62
+ });
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ },
68
+ async forgotPassword(email) {
69
+ await request('/forgot-password', {
70
+ method: 'POST',
71
+ body: JSON.stringify({ email }),
72
+ });
73
+ },
74
+ async resetPassword(token, newPassword) {
75
+ await request('/reset-password', {
76
+ method: 'POST',
77
+ body: JSON.stringify({ token, newPassword }),
78
+ });
79
+ },
80
+ async updateUser(data) {
81
+ const result = await request('/update-user', {
82
+ method: 'POST',
83
+ body: JSON.stringify(data),
84
+ });
85
+ return result.user;
86
+ },
87
+ };
88
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import type { AuthClient } from './types';
9
+ /**
10
+ * Options for creating an authenticated adapter.
11
+ */
12
+ export interface AuthenticatedAdapterOptions {
13
+ /** Base URL for the ObjectStack API */
14
+ baseUrl: string;
15
+ /** Auth client to get session tokens from */
16
+ authClient: AuthClient;
17
+ /** Additional adapter options */
18
+ [key: string]: unknown;
19
+ }
20
+ /**
21
+ * Creates an authenticated fetch wrapper that injects the Bearer token
22
+ * from the auth session into every request to the ObjectStack API.
23
+ *
24
+ * This is the recommended way to integrate authentication with
25
+ * @objectstack/client's ObjectStackAdapter.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { ObjectStackAdapter } from '@object-ui/data-objectstack';
30
+ * import { createAuthClient, createAuthenticatedFetch } from '@object-ui/auth';
31
+ *
32
+ * const authClient = createAuthClient({ baseURL: '/api/auth' });
33
+ * const authenticatedFetch = createAuthenticatedFetch(authClient);
34
+ *
35
+ * const adapter = new ObjectStackAdapter({
36
+ * baseUrl: '/api/v1',
37
+ * fetch: authenticatedFetch,
38
+ * });
39
+ * ```
40
+ */
41
+ export declare function createAuthenticatedFetch(authClient: AuthClient): (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
42
+ //# sourceMappingURL=createAuthenticatedFetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAuthenticatedFetch.d.ts","sourceRoot":"","sources":["../src/createAuthenticatedFetch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,UAAU,EAAE,UAAU,CAAC;IACvB,iCAAiC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,UAAU,GACrB,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CASrE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Creates an authenticated fetch wrapper that injects the Bearer token
10
+ * from the auth session into every request to the ObjectStack API.
11
+ *
12
+ * This is the recommended way to integrate authentication with
13
+ * @objectstack/client's ObjectStackAdapter.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * import { ObjectStackAdapter } from '@object-ui/data-objectstack';
18
+ * import { createAuthClient, createAuthenticatedFetch } from '@object-ui/auth';
19
+ *
20
+ * const authClient = createAuthClient({ baseURL: '/api/auth' });
21
+ * const authenticatedFetch = createAuthenticatedFetch(authClient);
22
+ *
23
+ * const adapter = new ObjectStackAdapter({
24
+ * baseUrl: '/api/v1',
25
+ * fetch: authenticatedFetch,
26
+ * });
27
+ * ```
28
+ */
29
+ export function createAuthenticatedFetch(authClient) {
30
+ return async (input, init) => {
31
+ const session = await authClient.getSession();
32
+ const headers = new Headers(init?.headers);
33
+ if (session?.session?.token) {
34
+ headers.set('Authorization', `Bearer ${session.session.token}`);
35
+ }
36
+ return fetch(input, { ...init, headers });
37
+ };
38
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * @object-ui/auth
10
+ *
11
+ * Authentication system for Object UI providing:
12
+ * - AuthProvider context for React apps
13
+ * - useAuth hook for accessing auth state and methods
14
+ * - AuthGuard component for route protection
15
+ * - LoginForm, RegisterForm, ForgotPasswordForm UI components
16
+ * - UserMenu component for authenticated user display
17
+ * - createAuthClient factory for auth backend integration
18
+ * - createAuthenticatedFetch for DataSource token injection
19
+ *
20
+ * @packageDocumentation
21
+ */
22
+ export { AuthProvider, type AuthProviderProps } from './AuthProvider';
23
+ export { useAuth } from './useAuth';
24
+ export { AuthGuard, type AuthGuardProps } from './AuthGuard';
25
+ export { LoginForm, type LoginFormProps } from './LoginForm';
26
+ export { RegisterForm, type RegisterFormProps } from './RegisterForm';
27
+ export { ForgotPasswordForm, type ForgotPasswordFormProps } from './ForgotPasswordForm';
28
+ export { UserMenu, type UserMenuProps } from './UserMenu';
29
+ export { createAuthClient } from './createAuthClient';
30
+ export { createAuthenticatedFetch, type AuthenticatedAdapterOptions } from './createAuthenticatedFetch';
31
+ export { getUserInitials } from './types';
32
+ export type { AuthUser, AuthSession, AuthState, AuthClient, AuthClientConfig, AuthProviderConfig, SignInCredentials, SignUpData, } from './types';
33
+ export type { AuthContextValue } from './AuthContext';
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,KAAK,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG1C,YAAY,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,GACX,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * @object-ui/auth
10
+ *
11
+ * Authentication system for Object UI providing:
12
+ * - AuthProvider context for React apps
13
+ * - useAuth hook for accessing auth state and methods
14
+ * - AuthGuard component for route protection
15
+ * - LoginForm, RegisterForm, ForgotPasswordForm UI components
16
+ * - UserMenu component for authenticated user display
17
+ * - createAuthClient factory for auth backend integration
18
+ * - createAuthenticatedFetch for DataSource token injection
19
+ *
20
+ * @packageDocumentation
21
+ */
22
+ export { AuthProvider } from './AuthProvider';
23
+ export { useAuth } from './useAuth';
24
+ export { AuthGuard } from './AuthGuard';
25
+ export { LoginForm } from './LoginForm';
26
+ export { RegisterForm } from './RegisterForm';
27
+ export { ForgotPasswordForm } from './ForgotPasswordForm';
28
+ export { UserMenu } from './UserMenu';
29
+ export { createAuthClient } from './createAuthClient';
30
+ export { createAuthenticatedFetch } from './createAuthenticatedFetch';
31
+ export { getUserInitials } from './types';
@@ -0,0 +1,112 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Authentication types for @object-ui/auth
10
+ */
11
+ /** Authenticated user information */
12
+ export interface AuthUser {
13
+ /** Unique user identifier */
14
+ id: string;
15
+ /** Display name */
16
+ name: string;
17
+ /** Email address */
18
+ email: string;
19
+ /** Profile image URL */
20
+ image?: string;
21
+ /** Primary role */
22
+ role?: string;
23
+ /** All assigned roles */
24
+ roles?: string[];
25
+ /** Email verification status */
26
+ emailVerified?: boolean;
27
+ /** Additional user metadata */
28
+ [key: string]: unknown;
29
+ }
30
+ /**
31
+ * Get user initials from their name or email.
32
+ * Returns up to 2 uppercase characters.
33
+ */
34
+ export declare function getUserInitials(user: Pick<AuthUser, 'name' | 'email'> | null | undefined): string;
35
+ /** Session information */
36
+ export interface AuthSession {
37
+ /** Access token */
38
+ token: string;
39
+ /** Token expiry timestamp */
40
+ expiresAt?: Date;
41
+ /** Refresh token */
42
+ refreshToken?: string;
43
+ }
44
+ /** Authentication state */
45
+ export interface AuthState {
46
+ /** Current authenticated user */
47
+ user: AuthUser | null;
48
+ /** Current session */
49
+ session: AuthSession | null;
50
+ /** Whether the user is authenticated */
51
+ isAuthenticated: boolean;
52
+ /** Whether auth state is loading */
53
+ isLoading: boolean;
54
+ /** Authentication error */
55
+ error: Error | null;
56
+ }
57
+ /** Sign in credentials */
58
+ export interface SignInCredentials {
59
+ email: string;
60
+ password: string;
61
+ }
62
+ /** Sign up data */
63
+ export interface SignUpData {
64
+ name: string;
65
+ email: string;
66
+ password: string;
67
+ }
68
+ /** Auth client configuration */
69
+ export interface AuthClientConfig {
70
+ /** Authentication server URL (e.g., "/api/auth") */
71
+ baseURL: string;
72
+ /** Custom fetch function for requests */
73
+ fetchFn?: typeof fetch;
74
+ }
75
+ /** Auth client interface - abstracts the underlying auth library */
76
+ export interface AuthClient {
77
+ /** Sign in with email/password */
78
+ signIn: (credentials: SignInCredentials) => Promise<{
79
+ user: AuthUser;
80
+ session: AuthSession;
81
+ }>;
82
+ /** Sign up with email/password */
83
+ signUp: (data: SignUpData) => Promise<{
84
+ user: AuthUser;
85
+ session: AuthSession;
86
+ }>;
87
+ /** Sign out */
88
+ signOut: () => Promise<void>;
89
+ /** Get current session */
90
+ getSession: () => Promise<{
91
+ user: AuthUser;
92
+ session: AuthSession;
93
+ } | null>;
94
+ /** Reset password request */
95
+ forgotPassword: (email: string) => Promise<void>;
96
+ /** Reset password with token */
97
+ resetPassword: (token: string, newPassword: string) => Promise<void>;
98
+ /** Update user profile */
99
+ updateUser: (data: Partial<AuthUser>) => Promise<AuthUser>;
100
+ }
101
+ /** Auth provider configuration */
102
+ export interface AuthProviderConfig {
103
+ /** Authentication server URL */
104
+ authUrl: string;
105
+ /** Auth client instance (if already created) */
106
+ client?: AuthClient;
107
+ /** Callback when auth state changes */
108
+ onAuthStateChange?: (state: AuthState) => void;
109
+ /** Path to redirect to when not authenticated */
110
+ redirectTo?: string;
111
+ }
112
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;GAEG;AAEH,qCAAqC;AACrC,MAAM,WAAW,QAAQ;IACvB,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,gCAAgC;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+BAA+B;IAC/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAWjG;AAED,0BAA0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACxB,iCAAiC;IACjC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,sBAAsB;IACtB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,wCAAwC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,oCAAoC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,0BAA0B;AAC1B,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,mBAAmB;AACnB,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gCAAgC;AAChC,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,kCAAkC;IAClC,MAAM,EAAE,CAAC,WAAW,EAAE,iBAAiB,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAC9F,kCAAkC;IAClC,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,CAAC;IAChF,eAAe;IACf,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0BAA0B;IAC1B,UAAU,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC3E,6BAA6B;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjD,gCAAgC;IAChC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,0BAA0B;IAC1B,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC5D;AAED,kCAAkC;AAClC,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC/C,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
package/dist/types.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Get user initials from their name or email.
10
+ * Returns up to 2 uppercase characters.
11
+ */
12
+ export function getUserInitials(user) {
13
+ if (!user)
14
+ return '?';
15
+ if (user.name) {
16
+ return user.name
17
+ .split(' ')
18
+ .map((n) => n[0])
19
+ .join('')
20
+ .toUpperCase()
21
+ .slice(0, 2);
22
+ }
23
+ return user.email?.[0]?.toUpperCase() ?? '?';
24
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { type AuthContextValue } from './AuthContext';
9
+ /**
10
+ * Hook to access authentication state and methods.
11
+ * Must be used within an AuthProvider.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * function UserProfile() {
16
+ * const { user, isAuthenticated, signOut } = useAuth();
17
+ * if (!isAuthenticated) return null;
18
+ * return <span>{user.name}</span>;
19
+ * }
20
+ * ```
21
+ */
22
+ export declare function useAuth(): AuthContextValue;
23
+ //# sourceMappingURL=useAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../src/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE/D;;;;;;;;;;;;GAYG;AACH,wBAAgB,OAAO,IAAI,gBAAgB,CAqB1C"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { useContext } from 'react';
9
+ import { AuthCtx } from './AuthContext';
10
+ /**
11
+ * Hook to access authentication state and methods.
12
+ * Must be used within an AuthProvider.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function UserProfile() {
17
+ * const { user, isAuthenticated, signOut } = useAuth();
18
+ * if (!isAuthenticated) return null;
19
+ * return <span>{user.name}</span>;
20
+ * }
21
+ * ```
22
+ */
23
+ export function useAuth() {
24
+ const ctx = useContext(AuthCtx);
25
+ if (!ctx) {
26
+ // Return a safe default when used outside AuthProvider
27
+ return {
28
+ user: null,
29
+ session: null,
30
+ isAuthenticated: false,
31
+ isLoading: false,
32
+ error: null,
33
+ signIn: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
34
+ signUp: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
35
+ signOut: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
36
+ updateUser: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
37
+ forgotPassword: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
38
+ resetPassword: async () => { throw new Error('useAuth must be used within an AuthProvider'); },
39
+ };
40
+ }
41
+ return ctx;
42
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@object-ui/auth",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "description": "Authentication system for Object UI with AuthProvider, useAuth hook, AuthGuard, and form components.",
7
+ "homepage": "https://www.objectui.org",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/objectstack-ai/objectui.git",
11
+ "directory": "packages/auth"
12
+ },
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "peerDependencies": {
26
+ "react": "^18.0.0 || ^19.0.0"
27
+ },
28
+ "dependencies": {
29
+ "@object-ui/types": "0.5.0"
30
+ },
31
+ "devDependencies": {
32
+ "@types/react": "^19.2.13",
33
+ "react": "^19.1.0",
34
+ "typescript": "^5.9.3",
35
+ "vitest": "^4.0.18"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc",
39
+ "clean": "rm -rf dist",
40
+ "test": "vitest run",
41
+ "type-check": "tsc --noEmit",
42
+ "lint": "eslint ."
43
+ }
44
+ }