@umituz/web-firebase 2.1.1 → 3.0.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.
Files changed (54) hide show
  1. package/package.json +12 -39
  2. package/src/domains/auth/entities/index.ts +60 -0
  3. package/src/domains/auth/index.ts +13 -0
  4. package/src/domains/auth/services/auth.service.ts +245 -0
  5. package/src/domains/auth/services/index.ts +7 -0
  6. package/src/domains/auth/types/auth-service.interface.ts +72 -0
  7. package/src/domains/auth/types/index.ts +5 -0
  8. package/src/domains/firestore/entities/index.ts +82 -0
  9. package/src/domains/firestore/index.ts +13 -0
  10. package/src/domains/firestore/services/firestore.service.ts +191 -0
  11. package/src/domains/firestore/services/index.ts +7 -0
  12. package/src/domains/firestore/types/firestore-service.interface.ts +64 -0
  13. package/src/domains/firestore/types/index.ts +5 -0
  14. package/src/domains/storage/entities/index.ts +94 -0
  15. package/src/domains/storage/index.ts +13 -0
  16. package/src/domains/storage/services/index.ts +7 -0
  17. package/src/domains/storage/services/storage.service.ts +223 -0
  18. package/src/domains/storage/types/index.ts +5 -0
  19. package/src/domains/storage/types/storage-service.interface.ts +120 -0
  20. package/src/index.ts +12 -16
  21. package/src/presentation/hooks/useAuth.ts +69 -26
  22. package/src/presentation/providers/FirebaseProvider.tsx +9 -14
  23. package/dist/application/index.d.mts +0 -273
  24. package/dist/application/index.d.ts +0 -273
  25. package/dist/application/index.js +0 -490
  26. package/dist/application/index.mjs +0 -19
  27. package/dist/chunk-34DL2QWQ.mjs +0 -87
  28. package/dist/chunk-4FP2ELQ5.mjs +0 -96
  29. package/dist/chunk-7TX3OU3O.mjs +0 -721
  30. package/dist/chunk-I6WGBPFB.mjs +0 -439
  31. package/dist/chunk-RZ4QR6TB.mjs +0 -96
  32. package/dist/chunk-U2XI4MGO.mjs +0 -397
  33. package/dist/domain/index.d.mts +0 -325
  34. package/dist/domain/index.d.ts +0 -325
  35. package/dist/domain/index.js +0 -662
  36. package/dist/domain/index.mjs +0 -36
  37. package/dist/file.repository.interface-v5vHgVsZ.d.mts +0 -241
  38. package/dist/file.repository.interface-v5vHgVsZ.d.ts +0 -241
  39. package/dist/firebase.entity-xvfEPjXZ.d.mts +0 -15
  40. package/dist/firebase.entity-xvfEPjXZ.d.ts +0 -15
  41. package/dist/index.d.mts +0 -14
  42. package/dist/index.d.ts +0 -14
  43. package/dist/index.js +0 -1833
  44. package/dist/index.mjs +0 -98
  45. package/dist/infrastructure/index.d.mts +0 -170
  46. package/dist/infrastructure/index.d.ts +0 -170
  47. package/dist/infrastructure/index.js +0 -856
  48. package/dist/infrastructure/index.mjs +0 -46
  49. package/dist/presentation/index.d.mts +0 -25
  50. package/dist/presentation/index.d.ts +0 -25
  51. package/dist/presentation/index.js +0 -105
  52. package/dist/presentation/index.mjs +0 -6
  53. package/dist/user.repository.interface-DS74TsJ5.d.mts +0 -298
  54. package/dist/user.repository.interface-DS74TsJ5.d.ts +0 -298
package/package.json CHANGED
@@ -1,49 +1,25 @@
1
1
  {
2
2
  "name": "@umituz/web-firebase",
3
- "version": "2.1.1",
4
- "description": "Comprehensive Firebase integration with DDD architecture for web applications",
5
- "main": "./dist/index.js",
6
- "module": "./dist/index.mjs",
7
- "types": "./dist/index.d.ts",
3
+ "version": "3.0.0",
4
+ "description": "Comprehensive Firebase integration with domain-based architecture for web applications",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
8
7
  "sideEffects": false,
9
8
  "publishConfig": {
10
9
  "access": "public"
11
10
  },
12
11
  "exports": {
13
- ".": {
14
- "types": "./dist/index.d.ts",
15
- "import": "./dist/index.mjs",
16
- "require": "./dist/index.js"
17
- },
18
- "./domain": {
19
- "types": "./dist/domain/index.d.ts",
20
- "import": "./dist/domain/index.mjs",
21
- "require": "./dist/domain/index.js"
22
- },
23
- "./application": {
24
- "types": "./dist/application/index.d.ts",
25
- "import": "./dist/application/index.mjs",
26
- "require": "./dist/application/index.js"
27
- },
28
- "./infrastructure": {
29
- "types": "./dist/infrastructure/index.d.ts",
30
- "import": "./dist/infrastructure/index.mjs",
31
- "require": "./dist/infrastructure/index.js"
32
- },
33
- "./presentation": {
34
- "types": "./dist/presentation/index.d.ts",
35
- "import": "./dist/presentation/index.mjs",
36
- "require": "./dist/presentation/index.js"
37
- }
12
+ ".": "./src/index.ts",
13
+ "./auth": "./src/domains/auth/index.ts",
14
+ "./firestore": "./src/domains/firestore/index.ts",
15
+ "./storage": "./src/domains/storage/index.ts",
16
+ "./package.json": "./package.json"
38
17
  },
39
18
  "files": [
40
- "dist",
41
19
  "src"
42
20
  ],
43
21
  "scripts": {
44
- "build": "tsup src/index.ts src/domain/index.ts src/application/index.ts src/infrastructure/index.ts src/presentation/index.ts --format cjs,esm --dts --clean --external react --external firebase --external firebase/app --external firebase/auth --external firebase/firestore --external firebase/storage --external firebase/functions",
45
- "dev": "tsup src/index.ts src/domain/index.ts src/application/index.ts src/infrastructure/index.ts src/presentation/index.ts --format cjs,esm --dts --watch --external react --external firebase",
46
- "lint": "tsc --noEmit"
22
+ "typecheck": "tsc --noEmit"
47
23
  },
48
24
  "keywords": [
49
25
  "firebase",
@@ -57,10 +33,8 @@
57
33
  "typescript",
58
34
  "ddd",
59
35
  "domain-driven-design",
60
- "clean-architecture",
61
- "repository-pattern",
62
- "use-cases",
63
- "hexagonal-architecture"
36
+ "package-driven",
37
+ "repository-pattern"
64
38
  ],
65
39
  "author": "umituz",
66
40
  "license": "MIT",
@@ -71,7 +45,6 @@
71
45
  "devDependencies": {
72
46
  "@types/react": "^18.2.0",
73
47
  "firebase": "^12.11.0",
74
- "tsup": "^8.0.0",
75
48
  "typescript": "^5.0.0"
76
49
  }
77
50
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Auth Domain Entities
3
+ * @description Core authentication-related entities
4
+ */
5
+
6
+ import type { User as FirebaseUser } from 'firebase/auth'
7
+
8
+ /**
9
+ * Auth User Entity
10
+ * Wrapper around Firebase User with application-specific data
11
+ */
12
+ export interface AuthUser {
13
+ readonly uid: string
14
+ readonly email: string | null
15
+ readonly emailVerified: boolean
16
+ readonly displayName: string | null
17
+ readonly photoURL: string | null
18
+ readonly phoneNumber: string | null
19
+ readonly isAnonymous: boolean
20
+ readonly tenantId: string | null
21
+ readonly providerId: string
22
+ readonly metadata: {
23
+ readonly creationTime?: number
24
+ readonly lastSignInTime?: number
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Auth State Entity
30
+ * Current authentication state
31
+ */
32
+ export interface AuthState {
33
+ readonly user: AuthUser | null
34
+ readonly isLoading: boolean
35
+ readonly isInitialized: boolean
36
+ readonly error: Error | null
37
+ }
38
+
39
+ /**
40
+ * Convert Firebase User to Auth User
41
+ */
42
+ export function toAuthUser(firebaseUser: FirebaseUser | null): AuthUser | null {
43
+ if (!firebaseUser) return null
44
+
45
+ return {
46
+ uid: firebaseUser.uid,
47
+ email: firebaseUser.email,
48
+ emailVerified: firebaseUser.emailVerified,
49
+ displayName: firebaseUser.displayName,
50
+ photoURL: firebaseUser.photoURL,
51
+ phoneNumber: firebaseUser.phoneNumber,
52
+ isAnonymous: firebaseUser.isAnonymous,
53
+ tenantId: firebaseUser.tenantId,
54
+ providerId: firebaseUser.providerId,
55
+ metadata: {
56
+ creationTime: firebaseUser.metadata.creationTime ? new Date(firebaseUser.metadata.creationTime).getTime() : undefined,
57
+ lastSignInTime: firebaseUser.metadata.lastSignInTime ? new Date(firebaseUser.metadata.lastSignInTime).getTime() : undefined,
58
+ },
59
+ }
60
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Auth Domain
3
+ * Complete Firebase Authentication integration
4
+ */
5
+
6
+ // Entities
7
+ export * from './entities'
8
+
9
+ // Types
10
+ export * from './types'
11
+
12
+ // Services
13
+ export * from './services'
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Auth Service
3
+ * @description Firebase Auth implementation of IAuthService
4
+ */
5
+
6
+ import {
7
+ signInWithEmailAndPassword,
8
+ signInWithPopup,
9
+ createUserWithEmailAndPassword,
10
+ signOut as firebaseSignOut,
11
+ sendPasswordResetEmail,
12
+ sendEmailVerification,
13
+ updateProfile as updateAuthProfile,
14
+ updateEmail as updateAuthEmail,
15
+ updatePassword as updateAuthPassword,
16
+ reauthenticateWithCredential,
17
+ EmailAuthProvider,
18
+ UserCredential,
19
+ } from 'firebase/auth'
20
+ import { GoogleAuthProvider } from 'firebase/auth'
21
+ import { getFirebaseAuth } from '../../../infrastructure/firebase/client'
22
+ import type { IAuthService } from '../types'
23
+ import type { AuthUser } from '../entities'
24
+
25
+ class AuthService implements IAuthService {
26
+ private get auth() {
27
+ return getFirebaseAuth()
28
+ }
29
+
30
+ // Authentication Methods
31
+
32
+ async signIn(email: string, password: string): Promise<UserCredential> {
33
+ try {
34
+ return await signInWithEmailAndPassword(this.auth, email, password)
35
+ } catch (error) {
36
+ throw this.handleAuthError(error)
37
+ }
38
+ }
39
+
40
+ async signUp(email: string, password: string, displayName: string): Promise<UserCredential> {
41
+ try {
42
+ const result = await createUserWithEmailAndPassword(this.auth, email, password)
43
+
44
+ // Update profile
45
+ await updateAuthProfile(result.user, { displayName })
46
+
47
+ // Send email verification
48
+ await sendEmailVerification(result.user)
49
+
50
+ return result
51
+ } catch (error) {
52
+ throw this.handleAuthError(error)
53
+ }
54
+ }
55
+
56
+ async signInWithGoogle(): Promise<UserCredential> {
57
+ try {
58
+ const provider = new GoogleAuthProvider()
59
+ provider.addScope('profile')
60
+ provider.addScope('email')
61
+
62
+ return await signInWithPopup(this.auth, provider)
63
+ } catch (error) {
64
+ throw this.handleAuthError(error)
65
+ }
66
+ }
67
+
68
+ async signOut(): Promise<void> {
69
+ try {
70
+ await firebaseSignOut(this.auth)
71
+ } catch (error) {
72
+ throw new Error('Sign out failed')
73
+ }
74
+ }
75
+
76
+ async sendPasswordReset(email: string): Promise<void> {
77
+ try {
78
+ await sendPasswordResetEmail(this.auth, email)
79
+ } catch (error) {
80
+ throw this.handleAuthError(error)
81
+ }
82
+ }
83
+
84
+ async resendEmailVerification(): Promise<void> {
85
+ try {
86
+ const user = this.auth.currentUser
87
+ if (!user) {
88
+ throw new Error('No user logged in')
89
+ }
90
+ await sendEmailVerification(user)
91
+ } catch (error) {
92
+ throw new Error('Failed to resend verification')
93
+ }
94
+ }
95
+
96
+ // Profile Management
97
+
98
+ async updateProfile(updates: { displayName?: string; photoURL?: string }): Promise<void> {
99
+ try {
100
+ const user = this.auth.currentUser
101
+ if (!user) {
102
+ throw new Error('No user logged in')
103
+ }
104
+
105
+ await updateAuthProfile(user, updates)
106
+ } catch (error) {
107
+ throw new Error('Profile update failed')
108
+ }
109
+ }
110
+
111
+ async updateEmail(newEmail: string, password: string): Promise<void> {
112
+ try {
113
+ const user = this.auth.currentUser
114
+ if (!user || !user.email) {
115
+ throw new Error('No user logged in')
116
+ }
117
+
118
+ const credential = EmailAuthProvider.credential(user.email, password)
119
+ await reauthenticateWithCredential(user, credential)
120
+ await updateAuthEmail(user, newEmail)
121
+ } catch (error) {
122
+ throw new Error('Email update failed')
123
+ }
124
+ }
125
+
126
+ async updatePassword(currentPassword: string, newPassword: string): Promise<void> {
127
+ try {
128
+ const user = this.auth.currentUser
129
+ if (!user || !user.email) {
130
+ throw new Error('No user logged in')
131
+ }
132
+
133
+ const credential = EmailAuthProvider.credential(user.email, currentPassword)
134
+ await reauthenticateWithCredential(user, credential)
135
+ await updateAuthPassword(user, newPassword)
136
+ } catch (error) {
137
+ throw new Error('Password update failed')
138
+ }
139
+ }
140
+
141
+ async deleteAccount(password: string): Promise<void> {
142
+ try {
143
+ const user = this.auth.currentUser
144
+ if (!user || !user.email) {
145
+ throw new Error('No user logged in')
146
+ }
147
+
148
+ const credential = EmailAuthProvider.credential(user.email, password)
149
+ await reauthenticateWithCredential(user, credential)
150
+ await user.delete()
151
+ } catch (error) {
152
+ throw new Error('Account deletion failed')
153
+ }
154
+ }
155
+
156
+ // State Management
157
+
158
+ getCurrentUser(): AuthUser | null {
159
+ const user = this.auth.currentUser
160
+ if (!user) return null
161
+
162
+ return {
163
+ uid: user.uid,
164
+ email: user.email,
165
+ emailVerified: user.emailVerified,
166
+ displayName: user.displayName,
167
+ photoURL: user.photoURL,
168
+ phoneNumber: user.phoneNumber,
169
+ isAnonymous: user.isAnonymous,
170
+ tenantId: user.tenantId,
171
+ providerId: user.providerId,
172
+ metadata: {
173
+ creationTime: user.metadata.creationTime ? new Date(user.metadata.creationTime).getTime() : undefined,
174
+ lastSignInTime: user.metadata.lastSignInTime ? new Date(user.metadata.lastSignInTime).getTime() : undefined,
175
+ },
176
+ }
177
+ }
178
+
179
+ onAuthStateChanged(
180
+ callback: (user: AuthUser | null) => void,
181
+ onError?: (error: Error) => void
182
+ ): () => void {
183
+ return this.auth.onAuthStateChanged(
184
+ (user) => {
185
+ callback(
186
+ user
187
+ ? {
188
+ uid: user.uid,
189
+ email: user.email,
190
+ emailVerified: user.emailVerified,
191
+ displayName: user.displayName,
192
+ photoURL: user.photoURL,
193
+ phoneNumber: user.phoneNumber,
194
+ isAnonymous: user.isAnonymous,
195
+ tenantId: user.tenantId,
196
+ providerId: user.providerId,
197
+ metadata: {
198
+ creationTime: user.metadata.creationTime ? new Date(user.metadata.creationTime).getTime() : undefined,
199
+ lastSignInTime: user.metadata.lastSignInTime ? new Date(user.metadata.lastSignInTime).getTime() : undefined,
200
+ },
201
+ }
202
+ : null
203
+ )
204
+ },
205
+ (error) => {
206
+ onError?.(error as Error)
207
+ }
208
+ )
209
+ }
210
+
211
+ /**
212
+ * Handle Firebase Auth errors
213
+ */
214
+ private handleAuthError(error: unknown): Error {
215
+ if (error instanceof Error && 'code' in error) {
216
+ const code = (error as { code: string }).code
217
+
218
+ switch (code) {
219
+ case 'auth/user-not-found':
220
+ case 'auth/wrong-password':
221
+ case 'auth/invalid-credential':
222
+ return new Error('Invalid credentials')
223
+ case 'auth/email-already-in-use':
224
+ return new Error('Email already in use')
225
+ case 'auth/weak-password':
226
+ return new Error('Password is too weak')
227
+ case 'auth/invalid-email':
228
+ return new Error('Invalid email')
229
+ case 'auth/user-disabled':
230
+ return new Error('Account disabled')
231
+ case 'auth/too-many-requests':
232
+ return new Error('Too many requests')
233
+ case 'auth/popup-closed-by-user':
234
+ return new Error('Sign in cancelled')
235
+ default:
236
+ return new Error(`Auth error: ${code}`)
237
+ }
238
+ }
239
+
240
+ return new Error('Unknown auth error')
241
+ }
242
+ }
243
+
244
+ // Export class and singleton instance
245
+ export const authService = new AuthService()
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Auth Domain Services
3
+ * Subpath: @umituz/web-firebase/auth
4
+ */
5
+
6
+ export { authService } from './auth.service'
7
+ export type { IAuthService } from '../types'
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Auth Service Interface
3
+ * @description Abstract interface for authentication operations
4
+ */
5
+
6
+ import type { UserCredential } from 'firebase/auth'
7
+ import type { AuthUser } from '../entities'
8
+
9
+ export interface IAuthService {
10
+ /**
11
+ * Sign in with email and password
12
+ */
13
+ signIn(email: string, password: string): Promise<UserCredential>
14
+
15
+ /**
16
+ * Sign up with email, password, and display name
17
+ */
18
+ signUp(email: string, password: string, displayName: string): Promise<UserCredential>
19
+
20
+ /**
21
+ * Sign in with Google OAuth
22
+ */
23
+ signInWithGoogle(): Promise<UserCredential>
24
+
25
+ /**
26
+ * Sign out current user
27
+ */
28
+ signOut(): Promise<void>
29
+
30
+ /**
31
+ * Send password reset email
32
+ */
33
+ sendPasswordReset(email: string): Promise<void>
34
+
35
+ /**
36
+ * Resend email verification
37
+ */
38
+ resendEmailVerification(): Promise<void>
39
+
40
+ /**
41
+ * Update user profile (displayName, photoURL)
42
+ */
43
+ updateProfile(updates: { displayName?: string; photoURL?: string }): Promise<void>
44
+
45
+ /**
46
+ * Update user email (requires password)
47
+ */
48
+ updateEmail(newEmail: string, password: string): Promise<void>
49
+
50
+ /**
51
+ * Update user password (requires current password)
52
+ */
53
+ updatePassword(currentPassword: string, newPassword: string): Promise<void>
54
+
55
+ /**
56
+ * Delete user account (requires password)
57
+ */
58
+ deleteAccount(password: string): Promise<void>
59
+
60
+ /**
61
+ * Get current authenticated user
62
+ */
63
+ getCurrentUser(): AuthUser | null
64
+
65
+ /**
66
+ * Subscribe to auth state changes
67
+ */
68
+ onAuthStateChanged(
69
+ callback: (user: AuthUser | null) => void,
70
+ onError?: (error: Error) => void
71
+ ): () => void
72
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Auth Domain Types
3
+ */
4
+
5
+ export * from './auth-service.interface';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Firestore Domain Entities
3
+ * @description Core Firestore-related entities
4
+ */
5
+
6
+ /**
7
+ * User Profile Value Object
8
+ * Immutable user profile data
9
+ */
10
+ export interface UserProfile {
11
+ readonly id: string
12
+ readonly email: string
13
+ readonly displayName: string
14
+ readonly photoURL?: string
15
+ readonly phoneNumber?: string
16
+ readonly createdAt: number
17
+ readonly updatedAt: number
18
+ readonly lastLoginAt: number
19
+ readonly emailVerified: boolean
20
+ }
21
+
22
+ /**
23
+ * User Notifications Settings
24
+ */
25
+ export interface UserNotifications {
26
+ email: boolean
27
+ push: boolean
28
+ marketing: boolean
29
+ security: boolean
30
+ weeklyDigest: boolean
31
+ }
32
+
33
+ /**
34
+ * User Privacy Settings
35
+ */
36
+ export interface UserPrivacy {
37
+ profileVisibility: 'public' | 'private'
38
+ showEmail: boolean
39
+ showPhone: boolean
40
+ dataSharing: boolean
41
+ }
42
+
43
+ /**
44
+ * User Settings Value Object
45
+ */
46
+ export interface UserSettings {
47
+ theme: 'light' | 'dark' | 'system'
48
+ language: string
49
+ timezone: string
50
+ currency: string
51
+ notifications: UserNotifications
52
+ privacy: UserPrivacy
53
+ }
54
+
55
+ /**
56
+ * User Subscription Value Object
57
+ */
58
+ export interface UserSubscription {
59
+ plan: 'free' | 'standard' | 'professional' | 'business'
60
+ status: 'active' | 'inactive' | 'canceled' | 'past_due'
61
+ polarCustomerId?: string
62
+ polarSubscriptionId?: string
63
+ currentPeriodStart?: number
64
+ currentPeriodEnd?: number
65
+ cancelAtPeriodEnd: boolean
66
+ readonly createdAt: number
67
+ readonly updatedAt: number
68
+ }
69
+
70
+ /**
71
+ * User Aggregate Root
72
+ * Main user document containing all user-related data
73
+ */
74
+ export interface User {
75
+ readonly profile: UserProfile
76
+ settings: UserSettings
77
+ subscription: UserSubscription
78
+ connectedAccounts?: any[]
79
+ content?: any[]
80
+ analytics?: any
81
+ credits?: any
82
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Firestore Domain
3
+ * Complete Cloud Firestore integration
4
+ */
5
+
6
+ // Entities
7
+ export * from './entities'
8
+
9
+ // Types
10
+ export * from './types'
11
+
12
+ // Services
13
+ export * from './services'