@bagelink/auth 1.1.39

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) 2023 Neveh Allon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # @bagelink/auth
2
+
3
+ A framework-agnostic authentication composable with Vue support.
4
+
5
+ ## Features
6
+
7
+ - Framework-agnostic reactivity system
8
+ - Automatic Vue integration
9
+ - TypeScript support
10
+ - Complete authentication flow (login, signup, password recovery, etc.)
11
+ - Error handling
12
+ - User management
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ bun add @bagelink/auth
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Basic Setup
23
+
24
+ ```typescript
25
+ import { initAuth } from '@bagelink/auth'
26
+
27
+ // Initialize with axios instance
28
+ const auth = initAuth({
29
+ axios: axiosInstance,
30
+ errorHandler: (error) => console.error(error)
31
+ })
32
+ ```
33
+
34
+ ### Vue Integration
35
+
36
+ ```typescript
37
+ // In your main.ts
38
+ import { createApp } from 'vue'
39
+ import { initAuth } from '@bagelink/auth'
40
+
41
+ const app = createApp(App)
42
+
43
+ // Initialize auth
44
+ const auth = initAuth({
45
+ axios: axiosInstance,
46
+ errorHandler: (error) => console.error(error)
47
+ })
48
+
49
+ // Use as a plugin
50
+ app.use(auth)
51
+
52
+ // In your components
53
+ import { useAuth } from '@bagelink/auth'
54
+
55
+ export default {
56
+ setup() {
57
+ const { login, currentUser, getIsLoggedIn } = useAuth()
58
+
59
+ // Use auth methods
60
+ const handleLogin = async () => {
61
+ await login({
62
+ email: 'user@example.com',
63
+ password: 'password'
64
+ })
65
+ }
66
+
67
+ return {
68
+ currentUser,
69
+ getIsLoggedIn,
70
+ handleLogin
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Vanilla JavaScript
77
+
78
+ ```typescript
79
+ import { initAuth } from '@bagelink/auth'
80
+
81
+ const auth = initAuth({
82
+ axios: axiosInstance,
83
+ errorHandler: (error) => console.error(error)
84
+ })
85
+
86
+ const { login, currentUser, getIsLoggedIn } = auth.useAuth()
87
+ ```
88
+
89
+ ## API
90
+
91
+ ### State
92
+
93
+ - `currentUser`: Current user information
94
+ - `passwordForm`: Password update form state
95
+
96
+ ### Getters
97
+
98
+ - `getFullName()`: Get user's full name
99
+ - `getIsLoggedIn()`: Check if user is logged in
100
+
101
+ ### Actions
102
+
103
+ - `login(credentials)`: Login with email and password
104
+ - `logout()`: Logout current user
105
+ - `checkAuth()`: Check authentication status
106
+ - `signup(user)`: Register new user
107
+ - `recoverPassword(email)`: Request password recovery
108
+ - `resetPassword(form)`: Reset password
109
+ - `updatePassword()`: Update current user's password
110
+ - `updateProfile(user)`: Update user profile
111
+ - `toggleUserStatus(userId, isActive)`: Toggle user active status
112
+ - `deleteUser(userId)`: Delete user
113
+
114
+ ## License
115
+
116
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,269 @@
1
+ 'use strict';
2
+
3
+ require('axios');
4
+
5
+ let api$1 = null;
6
+ function getApi() {
7
+ if (!api$1) {
8
+ throw new Error("API not initialized. Call initApi first.");
9
+ }
10
+ return api$1;
11
+ }
12
+
13
+ const ax = getApi();
14
+ ax.interceptors.request.use((config) => {
15
+ const token = localStorage.getItem("access_token");
16
+ if (token !== null && config.headers) {
17
+ config.headers.Authorization = `Bearer ${token}`;
18
+ }
19
+ const urlParams = new URLSearchParams(window.location.search);
20
+ const resetToken = urlParams.get("token");
21
+ if (resetToken !== null && config.headers) {
22
+ config.headers.Authorization = `Bearer ${resetToken}`;
23
+ }
24
+ return config;
25
+ });
26
+ async function login(username, password) {
27
+ const { data } = await ax.post("/auth/login", {
28
+ username: username.toLowerCase(),
29
+ password
30
+ });
31
+ localStorage.setItem("access_token", data.access_token);
32
+ }
33
+ function logout() {
34
+ localStorage.removeItem("access_token");
35
+ window.location.reload();
36
+ }
37
+ async function passwordRecovery(email) {
38
+ return ax.post(`/auth/password-recovery`, { email });
39
+ }
40
+ async function resetPassword(newPassword) {
41
+ return ax.post("/auth/reset-password", { new_password: newPassword });
42
+ }
43
+ async function getCurrentUser() {
44
+ return ax.get("/auth/me");
45
+ }
46
+ async function signup(user) {
47
+ return ax.post("/auth/signup", {
48
+ email: user.email.toLowerCase(),
49
+ password: user.password,
50
+ first_name: user.first_name,
51
+ last_name: user.last_name
52
+ });
53
+ }
54
+ async function updatePassword(form) {
55
+ return ax.put("/auth/password", {
56
+ current_password: form.current_password,
57
+ new_password: form.new_password
58
+ });
59
+ }
60
+ async function updateUserProfile(user) {
61
+ return ax.put("/auth/profile", user);
62
+ }
63
+ async function setUserStatus(userId, isActive) {
64
+ return ax.patch(`/auth/users/${userId}/status`, { is_active: isActive });
65
+ }
66
+ async function deleteUser(userId) {
67
+ return ax.delete(`/auth/users/${userId}`);
68
+ }
69
+
70
+ let api = null;
71
+ let onError = null;
72
+ let createRef = null;
73
+ const defaultReactiveFactory = (initial) => {
74
+ let value = initial;
75
+ return {
76
+ get value() {
77
+ return value;
78
+ },
79
+ set: (newValue) => {
80
+ value = newValue;
81
+ }
82
+ };
83
+ };
84
+ function createVueReactiveFactory(app) {
85
+ return (initial) => {
86
+ const refValue = app.ref(initial);
87
+ return {
88
+ get value() {
89
+ return refValue.value;
90
+ },
91
+ set: (v) => {
92
+ refValue.value = v;
93
+ }
94
+ };
95
+ };
96
+ }
97
+ function initAuth({
98
+ axios,
99
+ errorHandler,
100
+ reactive = defaultReactiveFactory
101
+ } = {}) {
102
+ api = axios || null;
103
+ onError = errorHandler || null;
104
+ createRef = reactive;
105
+ return {
106
+ install(app) {
107
+ if (app.ref) {
108
+ createRef = createVueReactiveFactory(app);
109
+ }
110
+ },
111
+ useAuth
112
+ };
113
+ }
114
+ function useAuth() {
115
+ if (!api || !createRef) {
116
+ throw new Error("Auth composable not initialized. Call initAuth first.");
117
+ }
118
+ const currentUser = createRef({
119
+ id: "",
120
+ email: "",
121
+ first_name: "",
122
+ last_name: "",
123
+ is_superuser: false,
124
+ is_active: false
125
+ });
126
+ const passwordForm = createRef({
127
+ current_password: "",
128
+ new_password: "",
129
+ confirmNewPassword: ""
130
+ });
131
+ const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`;
132
+ const getIsLoggedIn = () => currentUser.value.id.length > 0;
133
+ function handleError(error) {
134
+ if (onError) {
135
+ onError(error);
136
+ }
137
+ throw error;
138
+ }
139
+ async function logout$1() {
140
+ try {
141
+ await logout();
142
+ } catch (error) {
143
+ handleError(error);
144
+ }
145
+ }
146
+ async function login$1(credentials) {
147
+ const email = credentials.email.toLowerCase();
148
+ const { password } = credentials;
149
+ try {
150
+ await login(email, password);
151
+ await checkAuth();
152
+ } catch (error) {
153
+ handleError(error);
154
+ }
155
+ }
156
+ async function checkAuth() {
157
+ try {
158
+ if (!getIsLoggedIn()) {
159
+ const { data } = await getCurrentUser();
160
+ currentUser.set(data);
161
+ }
162
+ } catch (error) {
163
+ return false;
164
+ }
165
+ return getIsLoggedIn();
166
+ }
167
+ async function signup$1(user) {
168
+ try {
169
+ if (user.password !== user.confirmPassword) {
170
+ throw new Error("Passwords do not match");
171
+ }
172
+ const { data } = await signup(user);
173
+ currentUser.set(data);
174
+ } catch (error) {
175
+ handleError(error);
176
+ }
177
+ }
178
+ async function recoverPassword(email) {
179
+ try {
180
+ await passwordRecovery(email);
181
+ } catch (error) {
182
+ handleError(error);
183
+ }
184
+ }
185
+ async function resetPassword$1(form) {
186
+ try {
187
+ if (form.new_password !== form.confirmNewPassword) {
188
+ throw new Error("Passwords do not match");
189
+ }
190
+ await resetPassword(form.new_password);
191
+ form = {
192
+ current_password: "",
193
+ new_password: "",
194
+ confirmNewPassword: ""
195
+ };
196
+ } catch (error) {
197
+ handleError(error);
198
+ }
199
+ }
200
+ async function updatePassword$1() {
201
+ try {
202
+ if (passwordForm.value.new_password !== passwordForm.value.confirmNewPassword) {
203
+ throw new Error("Passwords do not match");
204
+ }
205
+ await updatePassword(passwordForm.value);
206
+ passwordForm.set({
207
+ current_password: "",
208
+ new_password: "",
209
+ confirmNewPassword: ""
210
+ });
211
+ } catch (error) {
212
+ handleError(error);
213
+ }
214
+ }
215
+ async function updateProfile(user) {
216
+ try {
217
+ const { data } = await updateUserProfile(user);
218
+ currentUser.set({ ...currentUser.value, ...data });
219
+ } catch (error) {
220
+ handleError(error);
221
+ }
222
+ }
223
+ async function toggleUserStatus(userId, isActive) {
224
+ try {
225
+ await setUserStatus(userId, isActive);
226
+ } catch (error) {
227
+ handleError(error);
228
+ }
229
+ }
230
+ async function deleteUser$1(userId) {
231
+ try {
232
+ await deleteUser(userId);
233
+ } catch (error) {
234
+ handleError(error);
235
+ }
236
+ }
237
+ return {
238
+ // State
239
+ currentUser,
240
+ passwordForm,
241
+ // Getters
242
+ getFullName,
243
+ getIsLoggedIn,
244
+ // Actions
245
+ logout: logout$1,
246
+ login: login$1,
247
+ checkAuth,
248
+ signup: signup$1,
249
+ recoverPassword,
250
+ resetPassword: resetPassword$1,
251
+ updatePassword: updatePassword$1,
252
+ updateProfile,
253
+ toggleUserStatus,
254
+ deleteUser: deleteUser$1
255
+ };
256
+ }
257
+
258
+ exports.deleteUser = deleteUser;
259
+ exports.getCurrentUser = getCurrentUser;
260
+ exports.initAuth = initAuth;
261
+ exports.login = login;
262
+ exports.logout = logout;
263
+ exports.passwordRecovery = passwordRecovery;
264
+ exports.resetPassword = resetPassword;
265
+ exports.setUserStatus = setUserStatus;
266
+ exports.signup = signup;
267
+ exports.updatePassword = updatePassword;
268
+ exports.updateUserProfile = updateUserProfile;
269
+ exports.useAuth = useAuth;
@@ -0,0 +1,74 @@
1
+ import { AxiosResponse, AxiosInstance } from 'axios';
2
+
3
+ interface User {
4
+ id: string;
5
+ email: string;
6
+ first_name: string;
7
+ last_name: string;
8
+ is_superuser: boolean;
9
+ is_active: boolean;
10
+ }
11
+ interface UserRegister {
12
+ email: string;
13
+ password: string;
14
+ first_name: string;
15
+ last_name: string;
16
+ }
17
+ interface NewUser extends UserRegister {
18
+ confirmPassword: string;
19
+ }
20
+ interface UpdatePasswordForm {
21
+ current_password: string;
22
+ new_password: string;
23
+ confirmNewPassword: string;
24
+ }
25
+ interface ReactiveRef<T> {
26
+ value: T;
27
+ set: (newValue: T) => void;
28
+ }
29
+ type ReactiveFactory = <T>(initial: T) => ReactiveRef<T>;
30
+
31
+ interface NewPasswordPayload {
32
+ token: string;
33
+ new_password: string;
34
+ }
35
+ declare function login(username: string, password: string): Promise<void>;
36
+ declare function logout(): void;
37
+ declare function passwordRecovery(email?: string): Promise<AxiosResponse>;
38
+ declare function resetPassword(newPassword: NewPasswordPayload['new_password']): Promise<AxiosResponse>;
39
+ declare function getCurrentUser(): Promise<AxiosResponse<User>>;
40
+ declare function signup(user: NewUser): Promise<AxiosResponse<User>>;
41
+ declare function updatePassword(form: UpdatePasswordForm): Promise<AxiosResponse>;
42
+ declare function updateUserProfile(user: Partial<User>): Promise<AxiosResponse<User>>;
43
+ declare function setUserStatus(userId: string, isActive: boolean): Promise<AxiosResponse>;
44
+ declare function deleteUser(userId: string): Promise<AxiosResponse>;
45
+
46
+ declare function initAuth({ axios, errorHandler, reactive }?: {
47
+ axios?: AxiosInstance;
48
+ errorHandler?: (error: any) => void;
49
+ reactive?: ReactiveFactory;
50
+ }): {
51
+ install(app: any): void;
52
+ useAuth: typeof useAuth;
53
+ };
54
+ declare function useAuth(): {
55
+ currentUser: ReactiveRef<User>;
56
+ passwordForm: ReactiveRef<UpdatePasswordForm>;
57
+ getFullName: () => string;
58
+ getIsLoggedIn: () => boolean;
59
+ logout: () => Promise<void>;
60
+ login: (credentials: {
61
+ email: string;
62
+ password: string;
63
+ }) => Promise<void>;
64
+ checkAuth: () => Promise<boolean>;
65
+ signup: (user: NewUser) => Promise<void>;
66
+ recoverPassword: (email: string) => Promise<void>;
67
+ resetPassword: (form: UpdatePasswordForm) => Promise<void>;
68
+ updatePassword: () => Promise<void>;
69
+ updateProfile: (user: Partial<User>) => Promise<void>;
70
+ toggleUserStatus: (userId: string, isActive: boolean) => Promise<void>;
71
+ deleteUser: (userId: string) => Promise<void>;
72
+ };
73
+
74
+ export { type NewPasswordPayload, type NewUser, type ReactiveFactory, type ReactiveRef, type UpdatePasswordForm, type User, type UserRegister, deleteUser, getCurrentUser, initAuth, login, logout, passwordRecovery, resetPassword, setUserStatus, signup, updatePassword, updateUserProfile, useAuth };
@@ -0,0 +1,74 @@
1
+ import { AxiosResponse, AxiosInstance } from 'axios';
2
+
3
+ interface User {
4
+ id: string;
5
+ email: string;
6
+ first_name: string;
7
+ last_name: string;
8
+ is_superuser: boolean;
9
+ is_active: boolean;
10
+ }
11
+ interface UserRegister {
12
+ email: string;
13
+ password: string;
14
+ first_name: string;
15
+ last_name: string;
16
+ }
17
+ interface NewUser extends UserRegister {
18
+ confirmPassword: string;
19
+ }
20
+ interface UpdatePasswordForm {
21
+ current_password: string;
22
+ new_password: string;
23
+ confirmNewPassword: string;
24
+ }
25
+ interface ReactiveRef<T> {
26
+ value: T;
27
+ set: (newValue: T) => void;
28
+ }
29
+ type ReactiveFactory = <T>(initial: T) => ReactiveRef<T>;
30
+
31
+ interface NewPasswordPayload {
32
+ token: string;
33
+ new_password: string;
34
+ }
35
+ declare function login(username: string, password: string): Promise<void>;
36
+ declare function logout(): void;
37
+ declare function passwordRecovery(email?: string): Promise<AxiosResponse>;
38
+ declare function resetPassword(newPassword: NewPasswordPayload['new_password']): Promise<AxiosResponse>;
39
+ declare function getCurrentUser(): Promise<AxiosResponse<User>>;
40
+ declare function signup(user: NewUser): Promise<AxiosResponse<User>>;
41
+ declare function updatePassword(form: UpdatePasswordForm): Promise<AxiosResponse>;
42
+ declare function updateUserProfile(user: Partial<User>): Promise<AxiosResponse<User>>;
43
+ declare function setUserStatus(userId: string, isActive: boolean): Promise<AxiosResponse>;
44
+ declare function deleteUser(userId: string): Promise<AxiosResponse>;
45
+
46
+ declare function initAuth({ axios, errorHandler, reactive }?: {
47
+ axios?: AxiosInstance;
48
+ errorHandler?: (error: any) => void;
49
+ reactive?: ReactiveFactory;
50
+ }): {
51
+ install(app: any): void;
52
+ useAuth: typeof useAuth;
53
+ };
54
+ declare function useAuth(): {
55
+ currentUser: ReactiveRef<User>;
56
+ passwordForm: ReactiveRef<UpdatePasswordForm>;
57
+ getFullName: () => string;
58
+ getIsLoggedIn: () => boolean;
59
+ logout: () => Promise<void>;
60
+ login: (credentials: {
61
+ email: string;
62
+ password: string;
63
+ }) => Promise<void>;
64
+ checkAuth: () => Promise<boolean>;
65
+ signup: (user: NewUser) => Promise<void>;
66
+ recoverPassword: (email: string) => Promise<void>;
67
+ resetPassword: (form: UpdatePasswordForm) => Promise<void>;
68
+ updatePassword: () => Promise<void>;
69
+ updateProfile: (user: Partial<User>) => Promise<void>;
70
+ toggleUserStatus: (userId: string, isActive: boolean) => Promise<void>;
71
+ deleteUser: (userId: string) => Promise<void>;
72
+ };
73
+
74
+ export { type NewPasswordPayload, type NewUser, type ReactiveFactory, type ReactiveRef, type UpdatePasswordForm, type User, type UserRegister, deleteUser, getCurrentUser, initAuth, login, logout, passwordRecovery, resetPassword, setUserStatus, signup, updatePassword, updateUserProfile, useAuth };
@@ -0,0 +1,74 @@
1
+ import { AxiosResponse, AxiosInstance } from 'axios';
2
+
3
+ interface User {
4
+ id: string;
5
+ email: string;
6
+ first_name: string;
7
+ last_name: string;
8
+ is_superuser: boolean;
9
+ is_active: boolean;
10
+ }
11
+ interface UserRegister {
12
+ email: string;
13
+ password: string;
14
+ first_name: string;
15
+ last_name: string;
16
+ }
17
+ interface NewUser extends UserRegister {
18
+ confirmPassword: string;
19
+ }
20
+ interface UpdatePasswordForm {
21
+ current_password: string;
22
+ new_password: string;
23
+ confirmNewPassword: string;
24
+ }
25
+ interface ReactiveRef<T> {
26
+ value: T;
27
+ set: (newValue: T) => void;
28
+ }
29
+ type ReactiveFactory = <T>(initial: T) => ReactiveRef<T>;
30
+
31
+ interface NewPasswordPayload {
32
+ token: string;
33
+ new_password: string;
34
+ }
35
+ declare function login(username: string, password: string): Promise<void>;
36
+ declare function logout(): void;
37
+ declare function passwordRecovery(email?: string): Promise<AxiosResponse>;
38
+ declare function resetPassword(newPassword: NewPasswordPayload['new_password']): Promise<AxiosResponse>;
39
+ declare function getCurrentUser(): Promise<AxiosResponse<User>>;
40
+ declare function signup(user: NewUser): Promise<AxiosResponse<User>>;
41
+ declare function updatePassword(form: UpdatePasswordForm): Promise<AxiosResponse>;
42
+ declare function updateUserProfile(user: Partial<User>): Promise<AxiosResponse<User>>;
43
+ declare function setUserStatus(userId: string, isActive: boolean): Promise<AxiosResponse>;
44
+ declare function deleteUser(userId: string): Promise<AxiosResponse>;
45
+
46
+ declare function initAuth({ axios, errorHandler, reactive }?: {
47
+ axios?: AxiosInstance;
48
+ errorHandler?: (error: any) => void;
49
+ reactive?: ReactiveFactory;
50
+ }): {
51
+ install(app: any): void;
52
+ useAuth: typeof useAuth;
53
+ };
54
+ declare function useAuth(): {
55
+ currentUser: ReactiveRef<User>;
56
+ passwordForm: ReactiveRef<UpdatePasswordForm>;
57
+ getFullName: () => string;
58
+ getIsLoggedIn: () => boolean;
59
+ logout: () => Promise<void>;
60
+ login: (credentials: {
61
+ email: string;
62
+ password: string;
63
+ }) => Promise<void>;
64
+ checkAuth: () => Promise<boolean>;
65
+ signup: (user: NewUser) => Promise<void>;
66
+ recoverPassword: (email: string) => Promise<void>;
67
+ resetPassword: (form: UpdatePasswordForm) => Promise<void>;
68
+ updatePassword: () => Promise<void>;
69
+ updateProfile: (user: Partial<User>) => Promise<void>;
70
+ toggleUserStatus: (userId: string, isActive: boolean) => Promise<void>;
71
+ deleteUser: (userId: string) => Promise<void>;
72
+ };
73
+
74
+ export { type NewPasswordPayload, type NewUser, type ReactiveFactory, type ReactiveRef, type UpdatePasswordForm, type User, type UserRegister, deleteUser, getCurrentUser, initAuth, login, logout, passwordRecovery, resetPassword, setUserStatus, signup, updatePassword, updateUserProfile, useAuth };
package/dist/index.mjs ADDED
@@ -0,0 +1,256 @@
1
+ import 'axios';
2
+
3
+ let api$1 = null;
4
+ function getApi() {
5
+ if (!api$1) {
6
+ throw new Error("API not initialized. Call initApi first.");
7
+ }
8
+ return api$1;
9
+ }
10
+
11
+ const ax = getApi();
12
+ ax.interceptors.request.use((config) => {
13
+ const token = localStorage.getItem("access_token");
14
+ if (token !== null && config.headers) {
15
+ config.headers.Authorization = `Bearer ${token}`;
16
+ }
17
+ const urlParams = new URLSearchParams(window.location.search);
18
+ const resetToken = urlParams.get("token");
19
+ if (resetToken !== null && config.headers) {
20
+ config.headers.Authorization = `Bearer ${resetToken}`;
21
+ }
22
+ return config;
23
+ });
24
+ async function login(username, password) {
25
+ const { data } = await ax.post("/auth/login", {
26
+ username: username.toLowerCase(),
27
+ password
28
+ });
29
+ localStorage.setItem("access_token", data.access_token);
30
+ }
31
+ function logout() {
32
+ localStorage.removeItem("access_token");
33
+ window.location.reload();
34
+ }
35
+ async function passwordRecovery(email) {
36
+ return ax.post(`/auth/password-recovery`, { email });
37
+ }
38
+ async function resetPassword(newPassword) {
39
+ return ax.post("/auth/reset-password", { new_password: newPassword });
40
+ }
41
+ async function getCurrentUser() {
42
+ return ax.get("/auth/me");
43
+ }
44
+ async function signup(user) {
45
+ return ax.post("/auth/signup", {
46
+ email: user.email.toLowerCase(),
47
+ password: user.password,
48
+ first_name: user.first_name,
49
+ last_name: user.last_name
50
+ });
51
+ }
52
+ async function updatePassword(form) {
53
+ return ax.put("/auth/password", {
54
+ current_password: form.current_password,
55
+ new_password: form.new_password
56
+ });
57
+ }
58
+ async function updateUserProfile(user) {
59
+ return ax.put("/auth/profile", user);
60
+ }
61
+ async function setUserStatus(userId, isActive) {
62
+ return ax.patch(`/auth/users/${userId}/status`, { is_active: isActive });
63
+ }
64
+ async function deleteUser(userId) {
65
+ return ax.delete(`/auth/users/${userId}`);
66
+ }
67
+
68
+ let api = null;
69
+ let onError = null;
70
+ let createRef = null;
71
+ const defaultReactiveFactory = (initial) => {
72
+ let value = initial;
73
+ return {
74
+ get value() {
75
+ return value;
76
+ },
77
+ set: (newValue) => {
78
+ value = newValue;
79
+ }
80
+ };
81
+ };
82
+ function createVueReactiveFactory(app) {
83
+ return (initial) => {
84
+ const refValue = app.ref(initial);
85
+ return {
86
+ get value() {
87
+ return refValue.value;
88
+ },
89
+ set: (v) => {
90
+ refValue.value = v;
91
+ }
92
+ };
93
+ };
94
+ }
95
+ function initAuth({
96
+ axios,
97
+ errorHandler,
98
+ reactive = defaultReactiveFactory
99
+ } = {}) {
100
+ api = axios || null;
101
+ onError = errorHandler || null;
102
+ createRef = reactive;
103
+ return {
104
+ install(app) {
105
+ if (app.ref) {
106
+ createRef = createVueReactiveFactory(app);
107
+ }
108
+ },
109
+ useAuth
110
+ };
111
+ }
112
+ function useAuth() {
113
+ if (!api || !createRef) {
114
+ throw new Error("Auth composable not initialized. Call initAuth first.");
115
+ }
116
+ const currentUser = createRef({
117
+ id: "",
118
+ email: "",
119
+ first_name: "",
120
+ last_name: "",
121
+ is_superuser: false,
122
+ is_active: false
123
+ });
124
+ const passwordForm = createRef({
125
+ current_password: "",
126
+ new_password: "",
127
+ confirmNewPassword: ""
128
+ });
129
+ const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`;
130
+ const getIsLoggedIn = () => currentUser.value.id.length > 0;
131
+ function handleError(error) {
132
+ if (onError) {
133
+ onError(error);
134
+ }
135
+ throw error;
136
+ }
137
+ async function logout$1() {
138
+ try {
139
+ await logout();
140
+ } catch (error) {
141
+ handleError(error);
142
+ }
143
+ }
144
+ async function login$1(credentials) {
145
+ const email = credentials.email.toLowerCase();
146
+ const { password } = credentials;
147
+ try {
148
+ await login(email, password);
149
+ await checkAuth();
150
+ } catch (error) {
151
+ handleError(error);
152
+ }
153
+ }
154
+ async function checkAuth() {
155
+ try {
156
+ if (!getIsLoggedIn()) {
157
+ const { data } = await getCurrentUser();
158
+ currentUser.set(data);
159
+ }
160
+ } catch (error) {
161
+ return false;
162
+ }
163
+ return getIsLoggedIn();
164
+ }
165
+ async function signup$1(user) {
166
+ try {
167
+ if (user.password !== user.confirmPassword) {
168
+ throw new Error("Passwords do not match");
169
+ }
170
+ const { data } = await signup(user);
171
+ currentUser.set(data);
172
+ } catch (error) {
173
+ handleError(error);
174
+ }
175
+ }
176
+ async function recoverPassword(email) {
177
+ try {
178
+ await passwordRecovery(email);
179
+ } catch (error) {
180
+ handleError(error);
181
+ }
182
+ }
183
+ async function resetPassword$1(form) {
184
+ try {
185
+ if (form.new_password !== form.confirmNewPassword) {
186
+ throw new Error("Passwords do not match");
187
+ }
188
+ await resetPassword(form.new_password);
189
+ form = {
190
+ current_password: "",
191
+ new_password: "",
192
+ confirmNewPassword: ""
193
+ };
194
+ } catch (error) {
195
+ handleError(error);
196
+ }
197
+ }
198
+ async function updatePassword$1() {
199
+ try {
200
+ if (passwordForm.value.new_password !== passwordForm.value.confirmNewPassword) {
201
+ throw new Error("Passwords do not match");
202
+ }
203
+ await updatePassword(passwordForm.value);
204
+ passwordForm.set({
205
+ current_password: "",
206
+ new_password: "",
207
+ confirmNewPassword: ""
208
+ });
209
+ } catch (error) {
210
+ handleError(error);
211
+ }
212
+ }
213
+ async function updateProfile(user) {
214
+ try {
215
+ const { data } = await updateUserProfile(user);
216
+ currentUser.set({ ...currentUser.value, ...data });
217
+ } catch (error) {
218
+ handleError(error);
219
+ }
220
+ }
221
+ async function toggleUserStatus(userId, isActive) {
222
+ try {
223
+ await setUserStatus(userId, isActive);
224
+ } catch (error) {
225
+ handleError(error);
226
+ }
227
+ }
228
+ async function deleteUser$1(userId) {
229
+ try {
230
+ await deleteUser(userId);
231
+ } catch (error) {
232
+ handleError(error);
233
+ }
234
+ }
235
+ return {
236
+ // State
237
+ currentUser,
238
+ passwordForm,
239
+ // Getters
240
+ getFullName,
241
+ getIsLoggedIn,
242
+ // Actions
243
+ logout: logout$1,
244
+ login: login$1,
245
+ checkAuth,
246
+ signup: signup$1,
247
+ recoverPassword,
248
+ resetPassword: resetPassword$1,
249
+ updatePassword: updatePassword$1,
250
+ updateProfile,
251
+ toggleUserStatus,
252
+ deleteUser: deleteUser$1
253
+ };
254
+ }
255
+
256
+ export { deleteUser, getCurrentUser, initAuth, login, logout, passwordRecovery, resetPassword, setUserStatus, signup, updatePassword, updateUserProfile, useAuth };
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@bagelink/auth",
3
+ "type": "module",
4
+ "version": "1.1.39",
5
+ "description": "Bagelink auth package",
6
+ "author": {
7
+ "name": "Bagel Studio",
8
+ "email": "info@bagelstudio.co.il",
9
+ "url": "https://bagelstudio.co.il"
10
+ },
11
+ "license": "MIT",
12
+ "homepage": "https://github.com/bageldb/bagelink/tree/master/packages/auth#readme",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/bageldb/bagelink.git",
16
+ "directory": "packages/auth"
17
+ },
18
+ "bugs": "https://github.com/bageldb/bagelink/issues",
19
+ "keywords": [],
20
+ "sideEffects": false,
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "require": "./dist/index.cjs",
25
+ "import": "./dist/index.mjs"
26
+ }
27
+ },
28
+ "main": "./dist/index.mjs",
29
+ "module": "./dist/index.mjs",
30
+ "types": "./dist/index.d.ts",
31
+ "files": [
32
+ "dist",
33
+ "src"
34
+ ],
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "dependencies": {
39
+ "axios": "^1.8.4"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^20.0.0",
43
+ "typescript": "^5.0.0",
44
+ "unbuild": "^2.0.0"
45
+ },
46
+ "scripts": {
47
+ "dev": "unbuild --stub",
48
+ "build": "unbuild",
49
+ "start": "tsx src/index.ts",
50
+ "watch": "tsx watch src/index.ts"
51
+ }
52
+ }
package/src/api/api.ts ADDED
@@ -0,0 +1,24 @@
1
+ import type { AxiosInstance } from 'axios'
2
+ import axios from 'axios'
3
+
4
+ let api: AxiosInstance | null = null
5
+
6
+ export function initApi(axiosInstance?: AxiosInstance) {
7
+ if (axiosInstance) {
8
+ api = axiosInstance
9
+ } else {
10
+ api = axios.create({
11
+ baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8000',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ })
16
+ }
17
+ }
18
+
19
+ export function getApi(): AxiosInstance {
20
+ if (!api) {
21
+ throw new Error('API not initialized. Call initApi first.')
22
+ }
23
+ return api
24
+ }
@@ -0,0 +1,81 @@
1
+ import type { AxiosResponse, InternalAxiosRequestConfig } from 'axios'
2
+ import type { User, NewUser, UpdatePasswordForm } from '../types'
3
+ import { getApi } from './api'
4
+
5
+ export interface NewPasswordPayload {
6
+ token: string
7
+ new_password: string
8
+ }
9
+
10
+ const ax = getApi()
11
+
12
+ ax.interceptors.request.use((config: InternalAxiosRequestConfig) => {
13
+ const token = localStorage.getItem('access_token')
14
+ if (token !== null && config.headers) {
15
+ config.headers.Authorization = `Bearer ${token}`
16
+ }
17
+
18
+ const urlParams = new URLSearchParams(window.location.search)
19
+ const resetToken = urlParams.get('token')
20
+
21
+ if (resetToken !== null && config.headers) {
22
+ config.headers.Authorization = `Bearer ${resetToken}`
23
+ }
24
+ return config
25
+ })
26
+
27
+ export async function login(username: string, password: string) {
28
+ const { data } = await ax.post('/auth/login', {
29
+ username: username.toLowerCase(),
30
+ password,
31
+ })
32
+ localStorage.setItem('access_token', data.access_token)
33
+ }
34
+
35
+ export function logout() {
36
+ localStorage.removeItem('access_token')
37
+ window.location.reload()
38
+ }
39
+
40
+ export async function passwordRecovery(email?: string): Promise<AxiosResponse> {
41
+ return ax.post(`/auth/password-recovery`, { email })
42
+ }
43
+
44
+ export async function resetPassword(
45
+ newPassword: NewPasswordPayload['new_password'],
46
+ ): Promise<AxiosResponse> {
47
+ return ax.post('/auth/reset-password', { new_password: newPassword })
48
+ }
49
+
50
+ // User Management APIs
51
+ export async function getCurrentUser(): Promise<AxiosResponse<User>> {
52
+ return ax.get('/auth/me')
53
+ }
54
+
55
+ export async function signup(user: NewUser): Promise<AxiosResponse<User>> {
56
+ return ax.post('/auth/signup', {
57
+ email: user.email.toLowerCase(),
58
+ password: user.password,
59
+ first_name: user.first_name,
60
+ last_name: user.last_name,
61
+ })
62
+ }
63
+
64
+ export async function updatePassword(form: UpdatePasswordForm): Promise<AxiosResponse> {
65
+ return ax.put('/auth/password', {
66
+ current_password: form.current_password,
67
+ new_password: form.new_password,
68
+ })
69
+ }
70
+
71
+ export async function updateUserProfile(user: Partial<User>): Promise<AxiosResponse<User>> {
72
+ return ax.put('/auth/profile', user)
73
+ }
74
+
75
+ export async function setUserStatus(userId: string, isActive: boolean): Promise<AxiosResponse> {
76
+ return ax.patch(`/auth/users/${userId}/status`, { is_active: isActive })
77
+ }
78
+
79
+ export async function deleteUser(userId: string): Promise<AxiosResponse> {
80
+ return ax.delete(`/auth/users/${userId}`)
81
+ }
@@ -0,0 +1,222 @@
1
+ import type { AxiosInstance } from 'axios'
2
+ import type { User, NewUser, UpdatePasswordForm, ReactiveFactory } from '../types'
3
+ import * as authApi from '../api/auth'
4
+
5
+ let api: AxiosInstance | null = null
6
+ let onError: ((error: any) => void) | null = null
7
+ let createRef: ReactiveFactory | null = null
8
+
9
+ const defaultReactiveFactory: ReactiveFactory = <T>(initial: T) => {
10
+ let value = initial
11
+ return {
12
+ get value() { return value },
13
+ set: (newValue: T) => { value = newValue }
14
+ }
15
+ }
16
+
17
+ // Vue plugin type
18
+ interface VuePlugin {
19
+ install: (app: any) => void
20
+ }
21
+
22
+ // Create Vue reactive factory
23
+ function createVueReactiveFactory(app: any): ReactiveFactory {
24
+ return <T>(initial: T) => {
25
+ const refValue = app.ref(initial)
26
+ return {
27
+ get value() { return refValue.value },
28
+ set: (v: T) => { refValue.value = v }
29
+ }
30
+ }
31
+ }
32
+
33
+ // Create plugin instance
34
+ export function initAuth({
35
+ axios,
36
+ errorHandler,
37
+ reactive = defaultReactiveFactory
38
+ }: {
39
+ axios?: AxiosInstance
40
+ errorHandler?: (error: any) => void
41
+ reactive?: ReactiveFactory
42
+ } = {}) {
43
+ api = axios || null
44
+ onError = errorHandler || null
45
+ createRef = reactive
46
+
47
+ // Return plugin interface
48
+ return {
49
+ install(app: any) {
50
+ // If Vue is detected, use Vue's reactivity
51
+ if (app.ref) {
52
+ createRef = createVueReactiveFactory(app)
53
+ }
54
+ },
55
+ useAuth
56
+ }
57
+ }
58
+
59
+ export function useAuth() {
60
+ if (!api || !createRef) {
61
+ throw new Error('Auth composable not initialized. Call initAuth first.')
62
+ }
63
+
64
+ // State
65
+ const currentUser = createRef<User>({
66
+ id: '',
67
+ email: '',
68
+ first_name: '',
69
+ last_name: '',
70
+ is_superuser: false,
71
+ is_active: false,
72
+ })
73
+
74
+ const passwordForm = createRef<UpdatePasswordForm>({
75
+ current_password: '',
76
+ new_password: '',
77
+ confirmNewPassword: '',
78
+ })
79
+
80
+ // Getters
81
+ const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`
82
+ const getIsLoggedIn = () => currentUser.value.id.length > 0
83
+
84
+ // Error handling
85
+ function handleError(error: any) {
86
+ if (onError) {
87
+ onError(error)
88
+ }
89
+ throw error
90
+ }
91
+
92
+ // Actions
93
+ async function logout() {
94
+ try {
95
+ await authApi.logout()
96
+ } catch (error: any) {
97
+ handleError(error)
98
+ }
99
+ }
100
+
101
+ async function login(credentials: { email: string, password: string }) {
102
+ const email = credentials.email.toLowerCase()
103
+ const { password } = credentials
104
+ try {
105
+ await authApi.login(email, password)
106
+ await checkAuth()
107
+ } catch (error: any) {
108
+ handleError(error)
109
+ }
110
+ }
111
+
112
+ async function checkAuth(): Promise<boolean> {
113
+ try {
114
+ if (!getIsLoggedIn()) {
115
+ const { data } = await authApi.getCurrentUser()
116
+ currentUser.set(data)
117
+ }
118
+ } catch (error: any) {
119
+ return false
120
+ }
121
+ return getIsLoggedIn()
122
+ }
123
+
124
+ async function signup(user: NewUser) {
125
+ try {
126
+ if (user.password !== user.confirmPassword) {
127
+ throw new Error('Passwords do not match')
128
+ }
129
+ const { data } = await authApi.signup(user)
130
+ currentUser.set(data)
131
+ } catch (error: any) {
132
+ handleError(error)
133
+ }
134
+ }
135
+
136
+ async function recoverPassword(email: string) {
137
+ try {
138
+ await authApi.passwordRecovery(email)
139
+ } catch (error: any) {
140
+ handleError(error)
141
+ }
142
+ }
143
+
144
+ async function resetPassword(form: UpdatePasswordForm) {
145
+ try {
146
+ if (form.new_password !== form.confirmNewPassword) {
147
+ throw new Error('Passwords do not match')
148
+ }
149
+ await authApi.resetPassword(form.new_password)
150
+ form = {
151
+ current_password: '',
152
+ new_password: '',
153
+ confirmNewPassword: '',
154
+ }
155
+ } catch (error: any) {
156
+ handleError(error)
157
+ }
158
+ }
159
+
160
+ async function updatePassword() {
161
+ try {
162
+ if (passwordForm.value.new_password !== passwordForm.value.confirmNewPassword) {
163
+ throw new Error('Passwords do not match')
164
+ }
165
+ await authApi.updatePassword(passwordForm.value)
166
+ passwordForm.set({
167
+ current_password: '',
168
+ new_password: '',
169
+ confirmNewPassword: '',
170
+ })
171
+ } catch (error: any) {
172
+ handleError(error)
173
+ }
174
+ }
175
+
176
+ async function updateProfile(user: Partial<User>) {
177
+ try {
178
+ const { data } = await authApi.updateUserProfile(user)
179
+ currentUser.set({ ...currentUser.value, ...data })
180
+ } catch (error: any) {
181
+ handleError(error)
182
+ }
183
+ }
184
+
185
+ async function toggleUserStatus(userId: string, isActive: boolean) {
186
+ try {
187
+ await authApi.setUserStatus(userId, isActive)
188
+ } catch (error: any) {
189
+ handleError(error)
190
+ }
191
+ }
192
+
193
+ async function deleteUser(userId: string) {
194
+ try {
195
+ await authApi.deleteUser(userId)
196
+ } catch (error: any) {
197
+ handleError(error)
198
+ }
199
+ }
200
+
201
+ return {
202
+ // State
203
+ currentUser,
204
+ passwordForm,
205
+
206
+ // Getters
207
+ getFullName,
208
+ getIsLoggedIn,
209
+
210
+ // Actions
211
+ logout,
212
+ login,
213
+ checkAuth,
214
+ signup,
215
+ recoverPassword,
216
+ resetPassword,
217
+ updatePassword,
218
+ updateProfile,
219
+ toggleUserStatus,
220
+ deleteUser,
221
+ }
222
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './api/auth'
2
+ export * from './composable/useAuth'
3
+ export * from './types'
package/src/types.ts ADDED
@@ -0,0 +1,32 @@
1
+ export interface User {
2
+ id: string
3
+ email: string
4
+ first_name: string
5
+ last_name: string
6
+ is_superuser: boolean
7
+ is_active: boolean
8
+ }
9
+
10
+ export interface UserRegister {
11
+ email: string
12
+ password: string
13
+ first_name: string
14
+ last_name: string
15
+ }
16
+
17
+ export interface NewUser extends UserRegister {
18
+ confirmPassword: string
19
+ }
20
+
21
+ export interface UpdatePasswordForm {
22
+ current_password: string
23
+ new_password: string
24
+ confirmNewPassword: string
25
+ }
26
+
27
+ export interface ReactiveRef<T> {
28
+ value: T
29
+ set: (newValue: T) => void
30
+ }
31
+
32
+ export type ReactiveFactory = <T>(initial: T) => ReactiveRef<T>