@umituz/web-firebase 1.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.
- package/dist/index.d.mts +96 -0
- package/dist/index.d.ts +96 -0
- package/dist/index.js +194 -0
- package/dist/index.mjs +185 -0
- package/package.json +50 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { FirebaseApp, FirebaseOptions } from 'firebase/app';
|
|
2
|
+
import { Auth, UserCredential } from 'firebase/auth';
|
|
3
|
+
import { Firestore, DocumentData, CollectionReference, QueryConstraint } from 'firebase/firestore';
|
|
4
|
+
import { FirebaseStorage } from 'firebase/storage';
|
|
5
|
+
import { Functions } from 'firebase/functions';
|
|
6
|
+
import * as _firebase_firestore from '@firebase/firestore';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Firebase Entity Types
|
|
10
|
+
*/
|
|
11
|
+
type FirebaseTimestamp = {
|
|
12
|
+
toDate(): Date;
|
|
13
|
+
} | Date;
|
|
14
|
+
interface FirebaseUser {
|
|
15
|
+
uid: string;
|
|
16
|
+
email: string | null;
|
|
17
|
+
displayName: string | null;
|
|
18
|
+
photoURL: string | null;
|
|
19
|
+
emailVerified: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Base Repository Interface
|
|
24
|
+
*/
|
|
25
|
+
interface IBaseRepository<T> {
|
|
26
|
+
getById(id: string, parentPath?: string): Promise<T | null>;
|
|
27
|
+
getAll(constraints?: any[], parentPath?: string): Promise<T[]>;
|
|
28
|
+
create(id: string, data: Omit<T, 'id'>, parentPath?: string): Promise<void>;
|
|
29
|
+
update(id: string, data: Partial<T>, parentPath?: string): Promise<void>;
|
|
30
|
+
delete(id: string, parentPath?: string): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Firebase Service Infrastructure
|
|
35
|
+
* @description Initialization and instance management for Firebase
|
|
36
|
+
*/
|
|
37
|
+
interface FirebaseInstances {
|
|
38
|
+
app: FirebaseApp;
|
|
39
|
+
auth: Auth;
|
|
40
|
+
db: Firestore;
|
|
41
|
+
storage: FirebaseStorage;
|
|
42
|
+
functions: Functions;
|
|
43
|
+
}
|
|
44
|
+
declare function initializeFirebase(config: FirebaseOptions, appName?: string): FirebaseInstances;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Firestore Repository Implementation
|
|
48
|
+
* @description Generic CRUD operations for Firestore collections
|
|
49
|
+
*/
|
|
50
|
+
declare class FirestoreRepository<T extends DocumentData> implements IBaseRepository<T> {
|
|
51
|
+
protected db: Firestore;
|
|
52
|
+
protected collectionName: string;
|
|
53
|
+
constructor(db: Firestore, collectionName: string);
|
|
54
|
+
protected getCollection(parentPath?: string): CollectionReference<T>;
|
|
55
|
+
protected getDocRef(id: string, parentPath?: string): _firebase_firestore.DocumentReference<DocumentData, DocumentData>;
|
|
56
|
+
getById(id: string, parentPath?: string): Promise<T | null>;
|
|
57
|
+
getAll(constraints?: QueryConstraint[], parentPath?: string): Promise<T[]>;
|
|
58
|
+
create(id: string, data: Omit<T, 'id'>, parentPath?: string): Promise<void>;
|
|
59
|
+
update(id: string, data: Partial<T>, parentPath?: string): Promise<void>;
|
|
60
|
+
delete(id: string, parentPath?: string): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Firebase Storage Utils
|
|
65
|
+
* @description Upload and delete helpers for Firebase Storage
|
|
66
|
+
*/
|
|
67
|
+
interface UploadResult {
|
|
68
|
+
url: string;
|
|
69
|
+
path: string;
|
|
70
|
+
}
|
|
71
|
+
declare function uploadFile(storage: FirebaseStorage, path: string, file: File | Blob): Promise<UploadResult>;
|
|
72
|
+
declare function uploadBase64(storage: FirebaseStorage, path: string, base64: string, mimeType?: string): Promise<UploadResult>;
|
|
73
|
+
declare function deleteFile(storage: FirebaseStorage, path: string): Promise<void>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* useFirebaseAuth Hook
|
|
77
|
+
* @description Hook to manage Firebase authentication state and operations
|
|
78
|
+
*/
|
|
79
|
+
interface UseFirebaseAuthOptions {
|
|
80
|
+
onUserChange?: (user: FirebaseUser | null) => void;
|
|
81
|
+
}
|
|
82
|
+
interface UseFirebaseAuthReturn {
|
|
83
|
+
user: FirebaseUser | null;
|
|
84
|
+
loading: boolean;
|
|
85
|
+
isAuthenticated: boolean;
|
|
86
|
+
signIn(email: string, password: string): Promise<UserCredential>;
|
|
87
|
+
signUp(email: string, password: string, name?: string): Promise<UserCredential>;
|
|
88
|
+
signOut(): Promise<void>;
|
|
89
|
+
updateUserProfile(name: string, photoURL?: string): Promise<void>;
|
|
90
|
+
updateUserPassword(newPassword: string): Promise<void>;
|
|
91
|
+
resetPassword(email: string): Promise<void>;
|
|
92
|
+
getIdToken(): Promise<string>;
|
|
93
|
+
}
|
|
94
|
+
declare function useFirebaseAuth(auth: Auth, options?: UseFirebaseAuthOptions): UseFirebaseAuthReturn;
|
|
95
|
+
|
|
96
|
+
export { type FirebaseInstances, type FirebaseTimestamp, type FirebaseUser, FirestoreRepository, type IBaseRepository, type UploadResult, type UseFirebaseAuthOptions, type UseFirebaseAuthReturn, deleteFile, initializeFirebase, uploadBase64, uploadFile, useFirebaseAuth };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { FirebaseApp, FirebaseOptions } from 'firebase/app';
|
|
2
|
+
import { Auth, UserCredential } from 'firebase/auth';
|
|
3
|
+
import { Firestore, DocumentData, CollectionReference, QueryConstraint } from 'firebase/firestore';
|
|
4
|
+
import { FirebaseStorage } from 'firebase/storage';
|
|
5
|
+
import { Functions } from 'firebase/functions';
|
|
6
|
+
import * as _firebase_firestore from '@firebase/firestore';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Firebase Entity Types
|
|
10
|
+
*/
|
|
11
|
+
type FirebaseTimestamp = {
|
|
12
|
+
toDate(): Date;
|
|
13
|
+
} | Date;
|
|
14
|
+
interface FirebaseUser {
|
|
15
|
+
uid: string;
|
|
16
|
+
email: string | null;
|
|
17
|
+
displayName: string | null;
|
|
18
|
+
photoURL: string | null;
|
|
19
|
+
emailVerified: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Base Repository Interface
|
|
24
|
+
*/
|
|
25
|
+
interface IBaseRepository<T> {
|
|
26
|
+
getById(id: string, parentPath?: string): Promise<T | null>;
|
|
27
|
+
getAll(constraints?: any[], parentPath?: string): Promise<T[]>;
|
|
28
|
+
create(id: string, data: Omit<T, 'id'>, parentPath?: string): Promise<void>;
|
|
29
|
+
update(id: string, data: Partial<T>, parentPath?: string): Promise<void>;
|
|
30
|
+
delete(id: string, parentPath?: string): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Firebase Service Infrastructure
|
|
35
|
+
* @description Initialization and instance management for Firebase
|
|
36
|
+
*/
|
|
37
|
+
interface FirebaseInstances {
|
|
38
|
+
app: FirebaseApp;
|
|
39
|
+
auth: Auth;
|
|
40
|
+
db: Firestore;
|
|
41
|
+
storage: FirebaseStorage;
|
|
42
|
+
functions: Functions;
|
|
43
|
+
}
|
|
44
|
+
declare function initializeFirebase(config: FirebaseOptions, appName?: string): FirebaseInstances;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Firestore Repository Implementation
|
|
48
|
+
* @description Generic CRUD operations for Firestore collections
|
|
49
|
+
*/
|
|
50
|
+
declare class FirestoreRepository<T extends DocumentData> implements IBaseRepository<T> {
|
|
51
|
+
protected db: Firestore;
|
|
52
|
+
protected collectionName: string;
|
|
53
|
+
constructor(db: Firestore, collectionName: string);
|
|
54
|
+
protected getCollection(parentPath?: string): CollectionReference<T>;
|
|
55
|
+
protected getDocRef(id: string, parentPath?: string): _firebase_firestore.DocumentReference<DocumentData, DocumentData>;
|
|
56
|
+
getById(id: string, parentPath?: string): Promise<T | null>;
|
|
57
|
+
getAll(constraints?: QueryConstraint[], parentPath?: string): Promise<T[]>;
|
|
58
|
+
create(id: string, data: Omit<T, 'id'>, parentPath?: string): Promise<void>;
|
|
59
|
+
update(id: string, data: Partial<T>, parentPath?: string): Promise<void>;
|
|
60
|
+
delete(id: string, parentPath?: string): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Firebase Storage Utils
|
|
65
|
+
* @description Upload and delete helpers for Firebase Storage
|
|
66
|
+
*/
|
|
67
|
+
interface UploadResult {
|
|
68
|
+
url: string;
|
|
69
|
+
path: string;
|
|
70
|
+
}
|
|
71
|
+
declare function uploadFile(storage: FirebaseStorage, path: string, file: File | Blob): Promise<UploadResult>;
|
|
72
|
+
declare function uploadBase64(storage: FirebaseStorage, path: string, base64: string, mimeType?: string): Promise<UploadResult>;
|
|
73
|
+
declare function deleteFile(storage: FirebaseStorage, path: string): Promise<void>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* useFirebaseAuth Hook
|
|
77
|
+
* @description Hook to manage Firebase authentication state and operations
|
|
78
|
+
*/
|
|
79
|
+
interface UseFirebaseAuthOptions {
|
|
80
|
+
onUserChange?: (user: FirebaseUser | null) => void;
|
|
81
|
+
}
|
|
82
|
+
interface UseFirebaseAuthReturn {
|
|
83
|
+
user: FirebaseUser | null;
|
|
84
|
+
loading: boolean;
|
|
85
|
+
isAuthenticated: boolean;
|
|
86
|
+
signIn(email: string, password: string): Promise<UserCredential>;
|
|
87
|
+
signUp(email: string, password: string, name?: string): Promise<UserCredential>;
|
|
88
|
+
signOut(): Promise<void>;
|
|
89
|
+
updateUserProfile(name: string, photoURL?: string): Promise<void>;
|
|
90
|
+
updateUserPassword(newPassword: string): Promise<void>;
|
|
91
|
+
resetPassword(email: string): Promise<void>;
|
|
92
|
+
getIdToken(): Promise<string>;
|
|
93
|
+
}
|
|
94
|
+
declare function useFirebaseAuth(auth: Auth, options?: UseFirebaseAuthOptions): UseFirebaseAuthReturn;
|
|
95
|
+
|
|
96
|
+
export { type FirebaseInstances, type FirebaseTimestamp, type FirebaseUser, FirestoreRepository, type IBaseRepository, type UploadResult, type UseFirebaseAuthOptions, type UseFirebaseAuthReturn, deleteFile, initializeFirebase, uploadBase64, uploadFile, useFirebaseAuth };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
FirestoreRepository: () => FirestoreRepository,
|
|
24
|
+
deleteFile: () => deleteFile,
|
|
25
|
+
initializeFirebase: () => initializeFirebase,
|
|
26
|
+
uploadBase64: () => uploadBase64,
|
|
27
|
+
uploadFile: () => uploadFile,
|
|
28
|
+
useFirebaseAuth: () => useFirebaseAuth
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/infrastructure/services/firebase.service.ts
|
|
33
|
+
var import_app = require("firebase/app");
|
|
34
|
+
var import_auth = require("firebase/auth");
|
|
35
|
+
var import_firestore = require("firebase/firestore");
|
|
36
|
+
var import_storage = require("firebase/storage");
|
|
37
|
+
var import_functions = require("firebase/functions");
|
|
38
|
+
function initializeFirebase(config, appName) {
|
|
39
|
+
const existing = (0, import_app.getApps)().find((a) => a.name === (appName ?? "[DEFAULT]"));
|
|
40
|
+
const app = existing ?? (0, import_app.initializeApp)(config, appName);
|
|
41
|
+
return {
|
|
42
|
+
app,
|
|
43
|
+
auth: (0, import_auth.getAuth)(app),
|
|
44
|
+
db: (0, import_firestore.getFirestore)(app),
|
|
45
|
+
storage: (0, import_storage.getStorage)(app),
|
|
46
|
+
functions: (0, import_functions.getFunctions)(app)
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/infrastructure/services/firestore.repository.ts
|
|
51
|
+
var import_firestore2 = require("firebase/firestore");
|
|
52
|
+
var FirestoreRepository = class {
|
|
53
|
+
constructor(db, collectionName) {
|
|
54
|
+
this.db = db;
|
|
55
|
+
this.collectionName = collectionName;
|
|
56
|
+
}
|
|
57
|
+
getCollection(parentPath) {
|
|
58
|
+
const fullPath = parentPath ? `${parentPath}/${this.collectionName}` : this.collectionName;
|
|
59
|
+
return (0, import_firestore2.collection)(this.db, fullPath);
|
|
60
|
+
}
|
|
61
|
+
getDocRef(id, parentPath) {
|
|
62
|
+
const fullPath = parentPath ? `${parentPath}/${this.collectionName}` : this.collectionName;
|
|
63
|
+
return (0, import_firestore2.doc)(this.db, fullPath, id);
|
|
64
|
+
}
|
|
65
|
+
async getById(id, parentPath) {
|
|
66
|
+
const snap = await (0, import_firestore2.getDoc)(this.getDocRef(id, parentPath));
|
|
67
|
+
return snap.exists() ? { id: snap.id, ...snap.data() } : null;
|
|
68
|
+
}
|
|
69
|
+
async getAll(constraints = [], parentPath) {
|
|
70
|
+
const q = (0, import_firestore2.query)(this.getCollection(parentPath), ...constraints);
|
|
71
|
+
const snap = await (0, import_firestore2.getDocs)(q);
|
|
72
|
+
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
73
|
+
}
|
|
74
|
+
async create(id, data, parentPath) {
|
|
75
|
+
await (0, import_firestore2.setDoc)(this.getDocRef(id, parentPath), {
|
|
76
|
+
...data,
|
|
77
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
78
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
async update(id, data, parentPath) {
|
|
82
|
+
await (0, import_firestore2.updateDoc)(this.getDocRef(id, parentPath), {
|
|
83
|
+
...data,
|
|
84
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async delete(id, parentPath) {
|
|
88
|
+
await (0, import_firestore2.deleteDoc)(this.getDocRef(id, parentPath));
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/infrastructure/utils/storage.util.ts
|
|
93
|
+
var import_storage2 = require("firebase/storage");
|
|
94
|
+
async function uploadFile(storage, path, file) {
|
|
95
|
+
const storageRef = (0, import_storage2.ref)(storage, path);
|
|
96
|
+
await (0, import_storage2.uploadBytes)(storageRef, file);
|
|
97
|
+
const url = await (0, import_storage2.getDownloadURL)(storageRef);
|
|
98
|
+
return { url, path };
|
|
99
|
+
}
|
|
100
|
+
async function uploadBase64(storage, path, base64, mimeType = "image/jpeg") {
|
|
101
|
+
const storageRef = (0, import_storage2.ref)(storage, path);
|
|
102
|
+
const dataUrl = base64.startsWith("data:") ? base64 : `data:${mimeType};base64,${base64}`;
|
|
103
|
+
await (0, import_storage2.uploadString)(storageRef, dataUrl, "data_url");
|
|
104
|
+
const url = await (0, import_storage2.getDownloadURL)(storageRef);
|
|
105
|
+
return { url, path };
|
|
106
|
+
}
|
|
107
|
+
async function deleteFile(storage, path) {
|
|
108
|
+
await (0, import_storage2.deleteObject)((0, import_storage2.ref)(storage, path));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/presentation/hooks/useFirebaseAuth.ts
|
|
112
|
+
var import_react = require("react");
|
|
113
|
+
var import_auth2 = require("firebase/auth");
|
|
114
|
+
function mapUser(u) {
|
|
115
|
+
return {
|
|
116
|
+
uid: u.uid,
|
|
117
|
+
email: u.email,
|
|
118
|
+
displayName: u.displayName,
|
|
119
|
+
photoURL: u.photoURL,
|
|
120
|
+
emailVerified: u.emailVerified
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function useFirebaseAuth(auth, options) {
|
|
124
|
+
const [user, setUser] = (0, import_react.useState)(null);
|
|
125
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
126
|
+
(0, import_react.useEffect)(() => {
|
|
127
|
+
const unsub = (0, import_auth2.onAuthStateChanged)(auth, (firebaseUser) => {
|
|
128
|
+
const mapped = firebaseUser ? mapUser(firebaseUser) : null;
|
|
129
|
+
setUser(mapped);
|
|
130
|
+
setLoading(false);
|
|
131
|
+
options?.onUserChange?.(mapped);
|
|
132
|
+
});
|
|
133
|
+
return unsub;
|
|
134
|
+
}, [auth, options]);
|
|
135
|
+
const signIn = (0, import_react.useCallback)(
|
|
136
|
+
(email, password) => (0, import_auth2.signInWithEmailAndPassword)(auth, email, password),
|
|
137
|
+
[auth]
|
|
138
|
+
);
|
|
139
|
+
const signUp = (0, import_react.useCallback)(
|
|
140
|
+
async (email, password, name) => {
|
|
141
|
+
const cred = await (0, import_auth2.createUserWithEmailAndPassword)(auth, email, password);
|
|
142
|
+
if (name && cred.user) await (0, import_auth2.updateProfile)(cred.user, { displayName: name });
|
|
143
|
+
return cred;
|
|
144
|
+
},
|
|
145
|
+
[auth]
|
|
146
|
+
);
|
|
147
|
+
const signOut = (0, import_react.useCallback)(() => (0, import_auth2.signOut)(auth), [auth]);
|
|
148
|
+
const updateUserProfile = (0, import_react.useCallback)(
|
|
149
|
+
async (name, photoURL) => {
|
|
150
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
151
|
+
await (0, import_auth2.updateProfile)(auth.currentUser, {
|
|
152
|
+
displayName: name,
|
|
153
|
+
...photoURL !== void 0 && { photoURL }
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
[auth]
|
|
157
|
+
);
|
|
158
|
+
const updateUserPassword = (0, import_react.useCallback)(
|
|
159
|
+
async (newPassword) => {
|
|
160
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
161
|
+
await (0, import_auth2.updatePassword)(auth.currentUser, newPassword);
|
|
162
|
+
},
|
|
163
|
+
[auth]
|
|
164
|
+
);
|
|
165
|
+
const resetPassword = (0, import_react.useCallback)(
|
|
166
|
+
(email) => (0, import_auth2.sendPasswordResetEmail)(auth, email),
|
|
167
|
+
[auth]
|
|
168
|
+
);
|
|
169
|
+
const getIdToken = (0, import_react.useCallback)(async () => {
|
|
170
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
171
|
+
return auth.currentUser.getIdToken();
|
|
172
|
+
}, [auth]);
|
|
173
|
+
return {
|
|
174
|
+
user,
|
|
175
|
+
loading,
|
|
176
|
+
isAuthenticated: !!user,
|
|
177
|
+
signIn,
|
|
178
|
+
signUp,
|
|
179
|
+
signOut,
|
|
180
|
+
updateUserProfile,
|
|
181
|
+
updateUserPassword,
|
|
182
|
+
resetPassword,
|
|
183
|
+
getIdToken
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
187
|
+
0 && (module.exports = {
|
|
188
|
+
FirestoreRepository,
|
|
189
|
+
deleteFile,
|
|
190
|
+
initializeFirebase,
|
|
191
|
+
uploadBase64,
|
|
192
|
+
uploadFile,
|
|
193
|
+
useFirebaseAuth
|
|
194
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// src/infrastructure/services/firebase.service.ts
|
|
2
|
+
import { initializeApp, getApps } from "firebase/app";
|
|
3
|
+
import { getAuth } from "firebase/auth";
|
|
4
|
+
import { getFirestore } from "firebase/firestore";
|
|
5
|
+
import { getStorage } from "firebase/storage";
|
|
6
|
+
import { getFunctions } from "firebase/functions";
|
|
7
|
+
function initializeFirebase(config, appName) {
|
|
8
|
+
const existing = getApps().find((a) => a.name === (appName ?? "[DEFAULT]"));
|
|
9
|
+
const app = existing ?? initializeApp(config, appName);
|
|
10
|
+
return {
|
|
11
|
+
app,
|
|
12
|
+
auth: getAuth(app),
|
|
13
|
+
db: getFirestore(app),
|
|
14
|
+
storage: getStorage(app),
|
|
15
|
+
functions: getFunctions(app)
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/infrastructure/services/firestore.repository.ts
|
|
20
|
+
import {
|
|
21
|
+
collection,
|
|
22
|
+
doc,
|
|
23
|
+
getDoc,
|
|
24
|
+
getDocs,
|
|
25
|
+
setDoc,
|
|
26
|
+
updateDoc,
|
|
27
|
+
deleteDoc,
|
|
28
|
+
query
|
|
29
|
+
} from "firebase/firestore";
|
|
30
|
+
var FirestoreRepository = class {
|
|
31
|
+
constructor(db, collectionName) {
|
|
32
|
+
this.db = db;
|
|
33
|
+
this.collectionName = collectionName;
|
|
34
|
+
}
|
|
35
|
+
getCollection(parentPath) {
|
|
36
|
+
const fullPath = parentPath ? `${parentPath}/${this.collectionName}` : this.collectionName;
|
|
37
|
+
return collection(this.db, fullPath);
|
|
38
|
+
}
|
|
39
|
+
getDocRef(id, parentPath) {
|
|
40
|
+
const fullPath = parentPath ? `${parentPath}/${this.collectionName}` : this.collectionName;
|
|
41
|
+
return doc(this.db, fullPath, id);
|
|
42
|
+
}
|
|
43
|
+
async getById(id, parentPath) {
|
|
44
|
+
const snap = await getDoc(this.getDocRef(id, parentPath));
|
|
45
|
+
return snap.exists() ? { id: snap.id, ...snap.data() } : null;
|
|
46
|
+
}
|
|
47
|
+
async getAll(constraints = [], parentPath) {
|
|
48
|
+
const q = query(this.getCollection(parentPath), ...constraints);
|
|
49
|
+
const snap = await getDocs(q);
|
|
50
|
+
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
51
|
+
}
|
|
52
|
+
async create(id, data, parentPath) {
|
|
53
|
+
await setDoc(this.getDocRef(id, parentPath), {
|
|
54
|
+
...data,
|
|
55
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
56
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
async update(id, data, parentPath) {
|
|
60
|
+
await updateDoc(this.getDocRef(id, parentPath), {
|
|
61
|
+
...data,
|
|
62
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async delete(id, parentPath) {
|
|
66
|
+
await deleteDoc(this.getDocRef(id, parentPath));
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/infrastructure/utils/storage.util.ts
|
|
71
|
+
import {
|
|
72
|
+
ref,
|
|
73
|
+
uploadBytes,
|
|
74
|
+
uploadString,
|
|
75
|
+
getDownloadURL,
|
|
76
|
+
deleteObject
|
|
77
|
+
} from "firebase/storage";
|
|
78
|
+
async function uploadFile(storage, path, file) {
|
|
79
|
+
const storageRef = ref(storage, path);
|
|
80
|
+
await uploadBytes(storageRef, file);
|
|
81
|
+
const url = await getDownloadURL(storageRef);
|
|
82
|
+
return { url, path };
|
|
83
|
+
}
|
|
84
|
+
async function uploadBase64(storage, path, base64, mimeType = "image/jpeg") {
|
|
85
|
+
const storageRef = ref(storage, path);
|
|
86
|
+
const dataUrl = base64.startsWith("data:") ? base64 : `data:${mimeType};base64,${base64}`;
|
|
87
|
+
await uploadString(storageRef, dataUrl, "data_url");
|
|
88
|
+
const url = await getDownloadURL(storageRef);
|
|
89
|
+
return { url, path };
|
|
90
|
+
}
|
|
91
|
+
async function deleteFile(storage, path) {
|
|
92
|
+
await deleteObject(ref(storage, path));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/presentation/hooks/useFirebaseAuth.ts
|
|
96
|
+
import { useState, useEffect, useCallback } from "react";
|
|
97
|
+
import {
|
|
98
|
+
onAuthStateChanged,
|
|
99
|
+
signInWithEmailAndPassword,
|
|
100
|
+
createUserWithEmailAndPassword,
|
|
101
|
+
signOut as firebaseSignOut,
|
|
102
|
+
updateProfile,
|
|
103
|
+
updatePassword,
|
|
104
|
+
sendPasswordResetEmail
|
|
105
|
+
} from "firebase/auth";
|
|
106
|
+
function mapUser(u) {
|
|
107
|
+
return {
|
|
108
|
+
uid: u.uid,
|
|
109
|
+
email: u.email,
|
|
110
|
+
displayName: u.displayName,
|
|
111
|
+
photoURL: u.photoURL,
|
|
112
|
+
emailVerified: u.emailVerified
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function useFirebaseAuth(auth, options) {
|
|
116
|
+
const [user, setUser] = useState(null);
|
|
117
|
+
const [loading, setLoading] = useState(true);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
const unsub = onAuthStateChanged(auth, (firebaseUser) => {
|
|
120
|
+
const mapped = firebaseUser ? mapUser(firebaseUser) : null;
|
|
121
|
+
setUser(mapped);
|
|
122
|
+
setLoading(false);
|
|
123
|
+
options?.onUserChange?.(mapped);
|
|
124
|
+
});
|
|
125
|
+
return unsub;
|
|
126
|
+
}, [auth, options]);
|
|
127
|
+
const signIn = useCallback(
|
|
128
|
+
(email, password) => signInWithEmailAndPassword(auth, email, password),
|
|
129
|
+
[auth]
|
|
130
|
+
);
|
|
131
|
+
const signUp = useCallback(
|
|
132
|
+
async (email, password, name) => {
|
|
133
|
+
const cred = await createUserWithEmailAndPassword(auth, email, password);
|
|
134
|
+
if (name && cred.user) await updateProfile(cred.user, { displayName: name });
|
|
135
|
+
return cred;
|
|
136
|
+
},
|
|
137
|
+
[auth]
|
|
138
|
+
);
|
|
139
|
+
const signOut = useCallback(() => firebaseSignOut(auth), [auth]);
|
|
140
|
+
const updateUserProfile = useCallback(
|
|
141
|
+
async (name, photoURL) => {
|
|
142
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
143
|
+
await updateProfile(auth.currentUser, {
|
|
144
|
+
displayName: name,
|
|
145
|
+
...photoURL !== void 0 && { photoURL }
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
[auth]
|
|
149
|
+
);
|
|
150
|
+
const updateUserPassword = useCallback(
|
|
151
|
+
async (newPassword) => {
|
|
152
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
153
|
+
await updatePassword(auth.currentUser, newPassword);
|
|
154
|
+
},
|
|
155
|
+
[auth]
|
|
156
|
+
);
|
|
157
|
+
const resetPassword = useCallback(
|
|
158
|
+
(email) => sendPasswordResetEmail(auth, email),
|
|
159
|
+
[auth]
|
|
160
|
+
);
|
|
161
|
+
const getIdToken = useCallback(async () => {
|
|
162
|
+
if (!auth.currentUser) throw new Error("No authenticated user");
|
|
163
|
+
return auth.currentUser.getIdToken();
|
|
164
|
+
}, [auth]);
|
|
165
|
+
return {
|
|
166
|
+
user,
|
|
167
|
+
loading,
|
|
168
|
+
isAuthenticated: !!user,
|
|
169
|
+
signIn,
|
|
170
|
+
signUp,
|
|
171
|
+
signOut,
|
|
172
|
+
updateUserProfile,
|
|
173
|
+
updateUserPassword,
|
|
174
|
+
resetPassword,
|
|
175
|
+
getIdToken
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
export {
|
|
179
|
+
FirestoreRepository,
|
|
180
|
+
deleteFile,
|
|
181
|
+
initializeFirebase,
|
|
182
|
+
uploadBase64,
|
|
183
|
+
uploadFile,
|
|
184
|
+
useFirebaseAuth
|
|
185
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@umituz/web-firebase",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Universal Firebase utilities for web applications",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./domain": "./src/domain/index.ts",
|
|
19
|
+
"./infrastructure": "./src/infrastructure/index.ts",
|
|
20
|
+
"./presentation": "./src/presentation/index.ts"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup src/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",
|
|
27
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch --external react --external firebase",
|
|
28
|
+
"lint": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"firebase",
|
|
32
|
+
"firestore",
|
|
33
|
+
"auth",
|
|
34
|
+
"storage",
|
|
35
|
+
"react",
|
|
36
|
+
"web"
|
|
37
|
+
],
|
|
38
|
+
"author": "Antigravity",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"firebase": ">=10",
|
|
42
|
+
"react": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/react": "^18.2.0",
|
|
46
|
+
"firebase": "^11.0.0",
|
|
47
|
+
"tsup": "^8.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|