@bagelink/auth 1.1.41 → 1.1.43

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/src/api/auth.ts CHANGED
@@ -21,88 +21,101 @@ import type {
21
21
  UpdatePasswordResponse,
22
22
  SignupResponse
23
23
  } from '../types'
24
- import { getApi } from './api'
25
-
26
- const ax = getApi()
27
-
28
- ax.interceptors.request.use((config: InternalAxiosRequestConfig) => {
29
- const token = localStorage.getItem('access_token')
30
- if (token !== null && config.headers) {
31
- config.headers.Authorization = `Bearer ${token}`
24
+ import axios from 'axios'
25
+
26
+ export class AuthApi {
27
+ private api: ReturnType<typeof axios.create>
28
+
29
+ constructor(baseURL?: string) {
30
+ this.api = axios.create({
31
+ baseURL,
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ },
35
+ })
36
+ this.setupInterceptors()
32
37
  }
33
38
 
34
- const urlParams = new URLSearchParams(window.location.search)
35
- const resetToken = urlParams.get('token')
39
+ private setupInterceptors() {
40
+ this.api.interceptors.request.use((config: InternalAxiosRequestConfig) => {
41
+ const token = localStorage.getItem('access_token')
42
+ if (token !== null && config.headers) {
43
+ config.headers.Authorization = `Bearer ${token}`
44
+ }
45
+
46
+ const urlParams = new URLSearchParams(window.location.search)
47
+ const resetToken = urlParams.get('token')
48
+
49
+ if (resetToken !== null && config.headers) {
50
+ config.headers.Authorization = `Bearer ${resetToken}`
51
+ }
52
+ return config
53
+ })
54
+ }
36
55
 
37
- if (resetToken !== null && config.headers) {
38
- config.headers.Authorization = `Bearer ${resetToken}`
56
+ async login(username: string, password: string): Promise<LoginResponse> {
57
+ const { data } = await this.api.post<Token>('/auth/login', {
58
+ username: username.toLowerCase(),
59
+ password,
60
+ })
61
+ localStorage.setItem('access_token', data.access_token)
62
+ return { data } as LoginResponse
39
63
  }
40
- return config
41
- })
42
-
43
- export async function login(username: string, password: string): Promise<LoginResponse> {
44
- const { data } = await ax.post<Token>('/auth/login', {
45
- username: username.toLowerCase(),
46
- password,
47
- })
48
- localStorage.setItem('access_token', data.access_token)
49
- return { data } as LoginResponse
50
- }
51
64
 
52
- export function logout() {
53
- localStorage.removeItem('access_token')
54
- window.location.reload()
55
- }
65
+ logout() {
66
+ localStorage.removeItem('access_token')
67
+ window.location.reload()
68
+ }
56
69
 
57
- export async function passwordRecovery(email?: string): Promise<PasswordRecoveryResponse> {
58
- return ax.post('/auth/password-recovery', { email })
59
- }
70
+ async passwordRecovery(email?: string): Promise<PasswordRecoveryResponse> {
71
+ return this.api.post('/auth/password-recovery', { email })
72
+ }
60
73
 
61
- export async function resetPassword(newPassword: NewPassword['new_password']): Promise<ResetPasswordResponse> {
62
- return ax.post('/auth/reset-password', { new_password: newPassword })
63
- }
74
+ async resetPassword(newPassword: NewPassword['new_password']): Promise<ResetPasswordResponse> {
75
+ return this.api.post('/auth/reset-password', { new_password: newPassword })
76
+ }
64
77
 
65
- // User Management APIs
66
- export async function getCurrentUser(): Promise<GetMeResponse> {
67
- return ax.get<SanitizedUserOut>('/users/me')
68
- }
78
+ async getCurrentUser(): Promise<GetMeResponse> {
79
+ return this.api.get<SanitizedUserOut>('/users/me')
80
+ }
69
81
 
70
- export async function signup(user: NewUser): Promise<SignupResponse> {
71
- return ax.post<SanitizedUserOut>('/users/signup', {
72
- email: user.email.toLowerCase(),
73
- password: user.password,
74
- first_name: user.first_name,
75
- last_name: user.last_name,
76
- })
77
- }
82
+ async signup(user: NewUser): Promise<SignupResponse> {
83
+ return this.api.post<SanitizedUserOut>('/users/signup', {
84
+ email: user.email.toLowerCase(),
85
+ password: user.password,
86
+ first_name: user.first_name,
87
+ last_name: user.last_name,
88
+ })
89
+ }
78
90
 
79
- export async function updatePassword(form: UpdatePasswordForm): Promise<UpdatePasswordResponse> {
80
- return ax.patch('/users/me/password', {
81
- current_password: form.current_password,
82
- new_password: form.new_password,
83
- })
84
- }
91
+ async updatePassword(form: UpdatePasswordForm): Promise<UpdatePasswordResponse> {
92
+ return this.api.patch('/users/me/password', {
93
+ current_password: form.current_password,
94
+ new_password: form.new_password,
95
+ })
96
+ }
85
97
 
86
- export async function updateUserProfile(user: Partial<User>): Promise<UpdateMeResponse> {
87
- return ax.patch<SanitizedUserOut>('/users/me', user)
88
- }
98
+ async updateUserProfile(user: Partial<User>): Promise<UpdateMeResponse> {
99
+ return this.api.patch<SanitizedUserOut>('/users/me', user)
100
+ }
89
101
 
90
- export async function setUserStatus(userId: string, isActive: boolean): Promise<UpdateUserResponse> {
91
- return ax.patch<SanitizedUserOut>(`/users/${userId}`, { is_active: isActive })
92
- }
102
+ async setUserStatus(userId: string, isActive: boolean): Promise<UpdateUserResponse> {
103
+ return this.api.patch<SanitizedUserOut>(`/users/${userId}`, { is_active: isActive })
104
+ }
93
105
 
94
- export async function deleteUser(userId: string): Promise<DeleteUserResponse> {
95
- return ax.delete(`/users/${userId}`)
96
- }
106
+ async deleteUser(userId: string): Promise<DeleteUserResponse> {
107
+ return this.api.delete(`/users/${userId}`)
108
+ }
97
109
 
98
- export async function getUsers(limit: number = 100, skip?: number): Promise<GetUsersResponse> {
99
- return ax.get<SanitizedUserList>('/users/', { params: { skip, limit } })
100
- }
110
+ async getUsers(limit: number = 100, skip?: number): Promise<GetUsersResponse> {
111
+ return this.api.get<SanitizedUserList>('/users/', { params: { skip, limit } })
112
+ }
101
113
 
102
- export async function createUser(user: UserCreate): Promise<CreateUserResponse> {
103
- return ax.post<SanitizedUserOut>('/users/', user)
104
- }
114
+ async createUser(user: UserCreate): Promise<CreateUserResponse> {
115
+ return this.api.post<SanitizedUserOut>('/users/', user)
116
+ }
105
117
 
106
- export async function getUser(userId: string): Promise<GetUserResponse> {
107
- return ax.get<SanitizedUserOut>(`/users/${userId}`)
118
+ async getUser(userId: string): Promise<GetUserResponse> {
119
+ return this.api.get<SanitizedUserOut>(`/users/${userId}`)
120
+ }
108
121
  }
@@ -1,124 +1,72 @@
1
- import type { AxiosInstance } from 'axios'
2
- import type { User, NewUser, UpdatePasswordForm, ReactiveFactory } from '../types'
3
- import { createDefaultApi } from '../api/api'
4
- import * as authApi from '../api/auth'
5
-
6
- let api: AxiosInstance
7
- let onError: ((error: any) => void)
8
- let createRef: ReactiveFactory
9
-
10
- const defaultReactiveFactory: ReactiveFactory = <T>(initial: T) => {
11
- let value = initial
12
- return {
13
- get value() { return value },
14
- set: (newValue: T) => { value = newValue }
1
+ import type { App } from 'vue'
2
+ import type { User, NewUser, UpdatePasswordForm } from '../types'
3
+ import { AuthApi } from '../api/auth'
4
+
5
+ // Global state
6
+ let authApi: AuthApi | null = null
7
+ const currentUser = {
8
+ value: {
9
+ id: '',
10
+ email: '',
11
+ first_name: '',
12
+ last_name: '',
13
+ is_superuser: false,
14
+ is_active: false,
15
+ } as User,
16
+ set: (newValue: User) => {
17
+ currentUser.value = newValue
15
18
  }
16
19
  }
17
20
 
18
- // Create Vue reactive factory
19
- function createVueReactiveFactory(app: any): ReactiveFactory {
20
- return <T>(initial: T) => {
21
- const refValue = app.ref(initial)
22
- return {
23
- get value() { return refValue.value },
24
- set: (v: T) => { refValue.value = v }
25
- }
21
+ // Initialize auth
22
+ export function initAuth(baseURL?: string) {
23
+ if (!authApi) {
24
+ authApi = new AuthApi(baseURL)
26
25
  }
27
- }
28
26
 
29
- // Create plugin instance
30
- export function initAuth({
31
- axios,
32
- errorHandler,
33
- reactive = defaultReactiveFactory,
34
- baseURL
35
- }: {
36
- axios?: AxiosInstance
37
- errorHandler?: (error: any) => void
38
- reactive?: ReactiveFactory
39
- baseURL?: string
40
- } = {}) {
41
- // Initialize API
42
- api = axios || createDefaultApi(baseURL)
43
-
44
- // Initialize error handler
45
- if (errorHandler) onError = errorHandler
46
-
47
- // Initialize reactive factory
48
- createRef = reactive
49
-
50
- // Return plugin interface
51
27
  return {
52
- install(app: any) {
53
- // If Vue is detected, use Vue's reactivity
54
- if (app.ref) {
55
- createRef = createVueReactiveFactory(app)
56
- }
57
- },
58
- useAuth
28
+ install(app: App) {
29
+ // Make auth available globally
30
+ app.config.globalProperties.$auth = useAuth()
31
+ }
59
32
  }
60
33
  }
61
34
 
35
+ // Composable
62
36
  export function useAuth() {
63
- if (!api || !createRef) {
64
- throw new Error('Auth composable not initialized. Call initAuth first.')
37
+ if (!authApi) {
38
+ throw new Error('Auth not initialized. Call initAuth first.')
65
39
  }
66
40
 
67
- // State
68
- const currentUser = createRef<User>({
69
- id: '',
70
- email: '',
71
- first_name: '',
72
- last_name: '',
73
- is_superuser: false,
74
- is_active: false,
75
- })
76
-
77
- const passwordForm = createRef<UpdatePasswordForm>({
78
- current_password: '',
79
- new_password: '',
80
- confirmNewPassword: '',
81
- })
82
-
83
41
  // Getters
84
42
  const getFullName = () => `${currentUser.value.first_name} ${currentUser.value.last_name}`
85
43
  const getIsLoggedIn = () => currentUser.value.id.length > 0
86
44
 
87
- // Error handling
88
- function handleError(error: any) {
89
- if (onError) {
90
- onError(error)
91
- }
92
- throw error
93
- }
94
-
95
45
  // Actions
96
46
  async function logout() {
97
47
  try {
98
- await authApi.logout()
99
- } catch (error: any) {
100
- handleError(error)
48
+ await authApi!.logout()
49
+ } catch (error) {
50
+ throw error
101
51
  }
102
52
  }
103
53
 
104
54
  async function login(credentials: { email: string, password: string }) {
105
- const email = credentials.email.toLowerCase()
106
- const { password } = credentials
107
55
  try {
108
- await authApi.login(email, password)
56
+ await authApi!.login(credentials.email.toLowerCase(), credentials.password)
109
57
  await checkAuth()
110
- } catch (error: any) {
111
- handleError(error)
58
+ } catch (error) {
59
+ throw error
112
60
  }
113
61
  }
114
62
 
115
63
  async function checkAuth(): Promise<boolean> {
116
64
  try {
117
65
  if (!getIsLoggedIn()) {
118
- const { data } = await authApi.getCurrentUser()
66
+ const { data } = await authApi!.getCurrentUser()
119
67
  currentUser.set(data)
120
68
  }
121
- } catch (error: any) {
69
+ } catch (error) {
122
70
  return false
123
71
  }
124
72
  return getIsLoggedIn()
@@ -129,82 +77,68 @@ export function useAuth() {
129
77
  if (user.password !== user.confirmPassword) {
130
78
  throw new Error('Passwords do not match')
131
79
  }
132
- const { data } = await authApi.signup(user)
80
+ const { data } = await authApi!.signup(user)
133
81
  currentUser.set(data)
134
- } catch (error: any) {
135
- handleError(error)
82
+ } catch (error) {
83
+ throw error
136
84
  }
137
85
  }
138
86
 
139
87
  async function recoverPassword(email: string) {
140
88
  try {
141
- await authApi.passwordRecovery(email)
142
- } catch (error: any) {
143
- handleError(error)
89
+ await authApi!.passwordRecovery(email)
90
+ } catch (error) {
91
+ throw error
144
92
  }
145
93
  }
146
94
 
147
- async function resetPassword(form: UpdatePasswordForm) {
95
+ async function resetPassword(newPassword: string) {
148
96
  try {
149
- if (form.new_password !== form.confirmNewPassword) {
150
- throw new Error('Passwords do not match')
151
- }
152
- await authApi.resetPassword(form.new_password)
153
- form = {
154
- current_password: '',
155
- new_password: '',
156
- confirmNewPassword: '',
157
- }
158
- } catch (error: any) {
159
- handleError(error)
97
+ await authApi!.resetPassword(newPassword)
98
+ } catch (error) {
99
+ throw error
160
100
  }
161
101
  }
162
102
 
163
- async function updatePassword() {
103
+ async function updatePassword(form: UpdatePasswordForm) {
164
104
  try {
165
- if (passwordForm.value.new_password !== passwordForm.value.confirmNewPassword) {
105
+ if (form.new_password !== form.confirmNewPassword) {
166
106
  throw new Error('Passwords do not match')
167
107
  }
168
- await authApi.updatePassword(passwordForm.value)
169
- passwordForm.set({
170
- current_password: '',
171
- new_password: '',
172
- confirmNewPassword: '',
173
- })
174
- } catch (error: any) {
175
- handleError(error)
108
+ await authApi!.updatePassword(form)
109
+ } catch (error) {
110
+ throw error
176
111
  }
177
112
  }
178
113
 
179
114
  async function updateProfile(user: Partial<User>) {
180
115
  try {
181
- const { data } = await authApi.updateUserProfile(user)
116
+ const { data } = await authApi!.updateUserProfile(user)
182
117
  currentUser.set({ ...currentUser.value, ...data })
183
- } catch (error: any) {
184
- handleError(error)
118
+ } catch (error) {
119
+ throw error
185
120
  }
186
121
  }
187
122
 
188
123
  async function toggleUserStatus(userId: string, isActive: boolean) {
189
124
  try {
190
- await authApi.setUserStatus(userId, isActive)
191
- } catch (error: any) {
192
- handleError(error)
125
+ await authApi!.setUserStatus(userId, isActive)
126
+ } catch (error) {
127
+ throw error
193
128
  }
194
129
  }
195
130
 
196
131
  async function deleteUser(userId: string) {
197
132
  try {
198
- await authApi.deleteUser(userId)
199
- } catch (error: any) {
200
- handleError(error)
133
+ await authApi!.deleteUser(userId)
134
+ } catch (error) {
135
+ throw error
201
136
  }
202
137
  }
203
138
 
204
139
  return {
205
140
  // State
206
141
  currentUser,
207
- passwordForm,
208
142
 
209
143
  // Getters
210
144
  getFullName,
package/src/api/api.ts DELETED
@@ -1,20 +0,0 @@
1
- import type { AxiosInstance } from 'axios'
2
- import axios from 'axios'
3
-
4
- const api: AxiosInstance | undefined = undefined
5
-
6
- export function getApi(): AxiosInstance {
7
- if (!api) {
8
- throw new Error('API not initialized. Call initAuth first.')
9
- }
10
- return api
11
- }
12
-
13
- export function createDefaultApi(baseURL?: string) {
14
- return axios.create({
15
- baseURL,
16
- headers: {
17
- 'Content-Type': 'application/json',
18
- },
19
- })
20
- }