@umituz/react-native-firebase 1.13.108 → 1.13.110
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/scripts/cli-parser.d.ts.map +1 -1
- package/dist/scripts/cli-parser.js +3 -0
- package/dist/scripts/cli-parser.js.map +1 -1
- package/dist/scripts/firestore-operations.d.ts.map +1 -1
- package/dist/scripts/firestore-operations.js +22 -13
- package/dist/scripts/firestore-operations.js.map +1 -1
- package/dist/scripts/firestore-seeding.d.ts.map +1 -1
- package/dist/scripts/firestore-seeding.js +20 -17
- package/dist/scripts/firestore-seeding.js.map +1 -1
- package/dist/scripts/init.d.ts +1 -1
- package/dist/scripts/init.d.ts.map +1 -1
- package/dist/scripts/init.js +5 -2
- package/dist/scripts/init.js.map +1 -1
- package/dist/scripts/user-commands.js +4 -4
- package/dist/scripts/user-commands.js.map +1 -1
- package/dist/scripts/utils.d.ts.map +1 -1
- package/dist/scripts/utils.js +6 -2
- package/dist/scripts/utils.js.map +1 -1
- package/package.json +2 -2
- package/scripts/cli-parser.ts +3 -0
- package/scripts/firestore-operations.ts +22 -13
- package/scripts/firestore-seeding.ts +21 -18
- package/scripts/init.ts +5 -2
- package/scripts/user-commands.ts +4 -4
- package/scripts/utils.ts +4 -2
- package/src/application/ports/IFirebaseClient.ts +3 -7
- package/src/auth/domain/entities/AnonymousUser.ts +4 -2
- package/src/auth/index.ts +2 -2
- package/src/auth/infrastructure/config/FirebaseAuthClient.ts +3 -0
- package/src/auth/infrastructure/services/account-deletion.service.ts +2 -9
- package/src/auth/infrastructure/services/anonymous-auth.service.ts +5 -1
- package/src/auth/infrastructure/services/apple-auth.service.ts +1 -8
- package/src/auth/infrastructure/services/apple-auth.types.ts +12 -0
- package/src/auth/infrastructure/services/auth-utils.service.ts +3 -17
- package/src/auth/infrastructure/services/google-auth.service.ts +1 -20
- package/src/auth/infrastructure/services/google-auth.types.ts +24 -0
- package/src/auth/infrastructure/services/reauthentication.service.ts +10 -4
- package/src/auth/presentation/hooks/useSocialAuth.ts +4 -24
- package/src/firestore/domain/constants/QuotaLimits.ts +1 -0
- package/src/firestore/domain/services/QuotaCalculator.ts +8 -7
- package/src/firestore/infrastructure/middleware/QuotaTrackingMiddleware.ts +21 -21
- package/src/firestore/infrastructure/repositories/BaseQueryRepository.ts +5 -7
- package/src/firestore/infrastructure/repositories/BaseRepository.ts +3 -18
- package/src/firestore/utils/dateUtils.ts +11 -5
- package/src/firestore/utils/document-mapper.helper.ts +1 -1
- package/src/firestore/utils/pagination.helper.ts +1 -1
- package/src/firestore/utils/quota-error-detector.util.ts +15 -10
- package/src/index.ts +1 -1
- package/src/infrastructure/config/FirebaseConfigLoader.ts +1 -1
- package/src/infrastructure/config/services/FirebaseServiceInitializer.ts +1 -1
- package/src/infrastructure/config/validators/FirebaseConfigValidator.ts +0 -4
- package/src/storage/types.ts +0 -2
- package/src/storage/uploader.ts +9 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-parser.d.ts","sourceRoot":"","sources":["../../scripts/cli-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,UAAU;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAyCtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"cli-parser.d.ts","sourceRoot":"","sources":["../../scripts/cli-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,UAAU;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,UAAU,CAyCtC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAaxD"}
|
|
@@ -94,6 +94,9 @@ function getProjectId(options) {
|
|
|
94
94
|
const saPath = path.resolve(process.cwd(), options.serviceAccountPath);
|
|
95
95
|
if (fs.existsSync(saPath)) {
|
|
96
96
|
const sa = JSON.parse(fs.readFileSync(saPath, "utf8"));
|
|
97
|
+
if (!sa.project_id) {
|
|
98
|
+
throw new Error("project_id not found in service account file.");
|
|
99
|
+
}
|
|
97
100
|
return sa.project_id;
|
|
98
101
|
}
|
|
99
102
|
throw new Error("Project ID not found. Use --project-id or ensure service account file exists.");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-parser.js","sourceRoot":"","sources":["../../scripts/cli-parser.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBH,8BAyCC;AAKD,
|
|
1
|
+
{"version":3,"file":"cli-parser.js","sourceRoot":"","sources":["../../scripts/cli-parser.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBH,8BAyCC;AAKD,oCAaC;AA/ED,2CAA6B;AAC7B,uCAAyB;AAgBzB;;GAEG;AACH,SAAgB,SAAS;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAClC,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,OAAO,GAAe;QAC1B,kBAAkB,EAAE,iCAAiC;QACrD,iBAAiB,EAAE,cAAc;QACjC,SAAS,EAAE,GAAG;QACd,UAAU,EAAE,GAAG;KAChB,CAAC;IAEF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACxB,QAAQ,GAAG,EAAE,CAAC;gBACZ,KAAK,iBAAiB;oBACpB,OAAO,CAAC,kBAAkB,GAAG,KAAK,CAAC;oBACnC,MAAM;gBACR,KAAK,YAAY;oBACf,OAAO,CAAC,SAAS,GAAG,KAAK,CAAC;oBAC1B,MAAM;gBACR,KAAK,oBAAoB;oBACvB,OAAO,CAAC,iBAAiB,GAAG,KAAK,CAAC;oBAClC,MAAM;gBACR,KAAK,YAAY;oBACf,OAAO,CAAC,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;oBAC3C,MAAM;gBACR,KAAK,aAAa;oBAChB,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC;oBAC5C,MAAM;YACV,CAAC;QACH,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QACD,CAAC,EAAE,CAAC;IACN,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,OAAmB;IAC9C,IAAI,OAAO,CAAC,SAAS;QAAE,OAAO,OAAO,CAAC,SAAS,CAAC;IAEhD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACvE,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,EAAE,CAAC,UAAU,CAAC;IACvB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;AACnG,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firestore-operations.d.ts","sourceRoot":"","sources":["../../scripts/firestore-operations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAIxC;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,cAAc,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,iBAAiB,EAAE,MAAM,EACzB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"firestore-operations.d.ts","sourceRoot":"","sources":["../../scripts/firestore-operations.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAIxC;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,cAAc,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC,CAyBjB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,iBAAiB,EAAE,MAAM,EACzB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACzD,OAAO,CAAC,MAAM,CAAC,CAwCjB"}
|
|
@@ -42,11 +42,14 @@ async function deleteUserSubcollection(db, subcollectionName, onProgress) {
|
|
|
42
42
|
const subcollectionRef = userDoc.ref.collection(subcollectionName);
|
|
43
43
|
const subcollectionSnapshot = await subcollectionRef.get();
|
|
44
44
|
if (!subcollectionSnapshot.empty) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
for (let i = 0; i < subcollectionSnapshot.docs.length; i += BATCH_SIZE) {
|
|
46
|
+
const chunk = subcollectionSnapshot.docs.slice(i, i + BATCH_SIZE);
|
|
47
|
+
const batch = db.batch();
|
|
48
|
+
chunk.forEach((doc) => batch.delete(doc.ref));
|
|
49
|
+
await batch.commit();
|
|
50
|
+
totalDeleted += chunk.length;
|
|
51
|
+
onProgress?.(totalDeleted);
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
return totalDeleted;
|
|
@@ -66,20 +69,26 @@ async function deleteAllData(db, onProgress) {
|
|
|
66
69
|
for (const subcollection of subcollections) {
|
|
67
70
|
const subSnapshot = await subcollection.get();
|
|
68
71
|
if (!subSnapshot.empty) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
for (let i = 0; i < subSnapshot.docs.length; i += BATCH_SIZE) {
|
|
73
|
+
const chunk = subSnapshot.docs.slice(i, i + BATCH_SIZE);
|
|
74
|
+
const batch = db.batch();
|
|
75
|
+
chunk.forEach((subDoc) => batch.delete(subDoc.ref));
|
|
76
|
+
await batch.commit();
|
|
77
|
+
totalDeleted += chunk.length;
|
|
78
|
+
}
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
// Delete main collection documents
|
|
78
84
|
if (!snapshot.empty) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
85
|
+
for (let i = 0; i < snapshot.docs.length; i += BATCH_SIZE) {
|
|
86
|
+
const chunk = snapshot.docs.slice(i, i + BATCH_SIZE);
|
|
87
|
+
const batch = db.batch();
|
|
88
|
+
chunk.forEach((doc) => batch.delete(doc.ref));
|
|
89
|
+
await batch.commit();
|
|
90
|
+
totalDeleted += chunk.length;
|
|
91
|
+
}
|
|
83
92
|
onProgress?.(collection.id, totalDeleted);
|
|
84
93
|
}
|
|
85
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firestore-operations.js","sourceRoot":"","sources":["../../scripts/firestore-operations.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AASH,4CA6BC;AAKD,
|
|
1
|
+
{"version":3,"file":"firestore-operations.js","sourceRoot":"","sources":["../../scripts/firestore-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firestore-seeding.d.ts","sourceRoot":"","sources":["../../scripts/firestore-seeding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C;;GAEG;AACH,wBAAsB,SAAS,CAC7B,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACzD,OAAO,CAAC,WAAW,CAAC,CA6BtB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,EACzB,IAAI,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACzD,OAAO,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"firestore-seeding.d.ts","sourceRoot":"","sources":["../../scripts/firestore-seeding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAI3C;;GAEG;AACH,wBAAsB,SAAS,CAC7B,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACzD,OAAO,CAAC,WAAW,CAAC,CA6BtB;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,EAC7B,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,MAAM,EACzB,IAAI,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACzD,OAAO,CAAC,WAAW,CAAC,CAiCtB"}
|
|
@@ -44,23 +44,26 @@ async function seedUserSubcollection(db, userId, subcollectionName, docs) {
|
|
|
44
44
|
processed: 0,
|
|
45
45
|
errors: [],
|
|
46
46
|
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
for (let i = 0; i < docs.length; i += BATCH_SIZE) {
|
|
48
|
+
const slice = docs.slice(i, i + BATCH_SIZE);
|
|
49
|
+
const batch = db.batch();
|
|
50
|
+
for (const { id, data } of slice) {
|
|
51
|
+
const ref = db
|
|
52
|
+
.collection("users")
|
|
53
|
+
.doc(userId)
|
|
54
|
+
.collection(subcollectionName)
|
|
55
|
+
.doc(id);
|
|
56
|
+
const clean = Object.fromEntries(Object.entries(data).filter(([, v]) => v !== undefined));
|
|
57
|
+
batch.set(ref, clean);
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await batch.commit();
|
|
61
|
+
result.processed += slice.length;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
result.success = false;
|
|
65
|
+
result.errors.push(`Failed to seed subcollection at index ${i}: ${error}`);
|
|
66
|
+
}
|
|
64
67
|
}
|
|
65
68
|
return result;
|
|
66
69
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"firestore-seeding.js","sourceRoot":"","sources":["../../scripts/firestore-seeding.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAUH,8BAiCC;AAKD,
|
|
1
|
+
{"version":3,"file":"firestore-seeding.js","sourceRoot":"","sources":["../../scripts/firestore-seeding.ts"],"names":[],"mappings":"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"}
|
package/dist/scripts/init.d.ts
CHANGED
|
@@ -25,5 +25,5 @@ export declare function getStorageAdmin(app: admin.app.App): admin.storage.Stora
|
|
|
25
25
|
/**
|
|
26
26
|
* Reset initialized app (for testing)
|
|
27
27
|
*/
|
|
28
|
-
export declare function resetFirebaseAdmin(): void
|
|
28
|
+
export declare function resetFirebaseAdmin(): Promise<void>;
|
|
29
29
|
//# sourceMappingURL=init.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../scripts/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAInD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAiB5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAE/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAEzE;AAED;;GAEG;AACH,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../scripts/init.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAInD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAiB5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAE/E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAEhE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAEzE;AAED;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKxD"}
|
package/dist/scripts/init.js
CHANGED
|
@@ -85,7 +85,10 @@ function getStorageAdmin(app) {
|
|
|
85
85
|
/**
|
|
86
86
|
* Reset initialized app (for testing)
|
|
87
87
|
*/
|
|
88
|
-
function resetFirebaseAdmin() {
|
|
89
|
-
initializedApp
|
|
88
|
+
async function resetFirebaseAdmin() {
|
|
89
|
+
if (initializedApp) {
|
|
90
|
+
await initializedApp.delete();
|
|
91
|
+
initializedApp = null;
|
|
92
|
+
}
|
|
90
93
|
}
|
|
91
94
|
//# sourceMappingURL=init.js.map
|
package/dist/scripts/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../scripts/init.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYH,8CAiBC;AAKD,8CAEC;AAKD,oCAEC;AAKD,0CAEC;AAKD,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../scripts/init.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYH,8CAiBC;AAKD,8CAEC;AAKD,oCAEC;AAKD,0CAEC;AAKD,gDAKC;AA1DD,sDAAwC;AAGxC,IAAI,cAAc,GAAyB,IAAI,CAAC;AAEhD;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,MAA2B;IAC3D,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC;QAChC,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC;QACnC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC;QAC5D,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CAAC;IAEH,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAAC,GAAkB;IAClD,OAAO,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,GAAkB;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED;;GAEG;AACH,SAAgB,eAAe,CAAC,GAAkB;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,kBAAkB;IACtC,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC"}
|
|
@@ -73,16 +73,16 @@ async function addUserCredits(db, userId, credits, collectionName = "user_credit
|
|
|
73
73
|
const updates = {
|
|
74
74
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
75
75
|
};
|
|
76
|
-
if (credits.text) {
|
|
76
|
+
if (credits.text !== undefined) {
|
|
77
77
|
updates.text = admin.firestore.FieldValue.increment(credits.text);
|
|
78
78
|
}
|
|
79
|
-
if (credits.image) {
|
|
79
|
+
if (credits.image !== undefined) {
|
|
80
80
|
updates.image = admin.firestore.FieldValue.increment(credits.image);
|
|
81
81
|
}
|
|
82
|
-
if (credits.video) {
|
|
82
|
+
if (credits.video !== undefined) {
|
|
83
83
|
updates.video = admin.firestore.FieldValue.increment(credits.video);
|
|
84
84
|
}
|
|
85
|
-
if (credits.audio) {
|
|
85
|
+
if (credits.audio !== undefined) {
|
|
86
86
|
updates.audio = admin.firestore.FieldValue.increment(credits.audio);
|
|
87
87
|
}
|
|
88
88
|
await db.collection(collectionName).doc(userId).update(updates);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-commands.js","sourceRoot":"","sources":["../../scripts/user-commands.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQH,sDA+BC;AAKD,wCAwBC;AAKD,wCAgBC;AAKD,8CAMC;AAlGD,sDAAwC;AAGxC;;GAEG;AACI,KAAK,UAAU,qBAAqB,CACzC,EAA6B,EAC7B,MAAc,EACd,MAAqB;IAErB,MAAM,EAAE,cAAc,GAAG,cAAc,EAAE,SAAS,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC;IAElF,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC;IAEzD,MAAM,OAAO,GAGT;QACF,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;IAEF,MAAM,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9E,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,IAAI,IAAI,EAAE;QACrB,SAAS,EAAE,IAAI,IAAI,EAAE;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,cAAc,CAClC,EAA6B,EAC7B,MAAc,EACd,OAA0E,EAC1E,cAAc,GAAG,cAAc;IAE/B,MAAM,OAAO,GAA+C;QAC1D,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,eAAe,EAAE;KACxD,CAAC;IAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"user-commands.js","sourceRoot":"","sources":["../../scripts/user-commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../scripts/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAKjC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../scripts/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAKjC;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAGzC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOjD;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,SAAM,EAAE,MAAM,SAAK,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK/C"}
|
package/dist/scripts/utils.js
CHANGED
|
@@ -34,6 +34,8 @@ function randomDate(daysAgo) {
|
|
|
34
34
|
* Get random item from array
|
|
35
35
|
*/
|
|
36
36
|
function randomItem(arr) {
|
|
37
|
+
if (arr.length === 0)
|
|
38
|
+
throw new Error("Cannot pick random item from empty array");
|
|
37
39
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
38
40
|
}
|
|
39
41
|
/**
|
|
@@ -60,9 +62,11 @@ function sleep(ms) {
|
|
|
60
62
|
function formatBytes(bytes) {
|
|
61
63
|
if (bytes === 0)
|
|
62
64
|
return "0 Bytes";
|
|
65
|
+
if (bytes < 0)
|
|
66
|
+
return "-" + formatBytes(-bytes);
|
|
63
67
|
const k = 1024;
|
|
64
|
-
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
65
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
68
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
69
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
|
|
66
70
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
67
71
|
}
|
|
68
72
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../scripts/utils.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAKH,4BAKC;AAKD,gCAMC;AAKD,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../scripts/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-firebase",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.110",
|
|
4
4
|
"description": "Unified Firebase package for React Native apps - Auth and Firestore services using Firebase JS SDK (no native modules).",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@types/react": "~19.1.10",
|
|
56
56
|
"@typescript-eslint/eslint-plugin": "^8.52.0",
|
|
57
57
|
"@typescript-eslint/parser": "^8.52.0",
|
|
58
|
-
"@umituz/react-native-design-system": "
|
|
58
|
+
"@umituz/react-native-design-system": "^4.23.58",
|
|
59
59
|
"eslint": "^9.39.2",
|
|
60
60
|
"eslint-plugin-react": "^7.37.5",
|
|
61
61
|
"eslint-plugin-react-native": "^5.0.0",
|
package/scripts/cli-parser.ts
CHANGED
|
@@ -75,6 +75,9 @@ export function getProjectId(options: CLIOptions): string {
|
|
|
75
75
|
const saPath = path.resolve(process.cwd(), options.serviceAccountPath);
|
|
76
76
|
if (fs.existsSync(saPath)) {
|
|
77
77
|
const sa = JSON.parse(fs.readFileSync(saPath, "utf8"));
|
|
78
|
+
if (!sa.project_id) {
|
|
79
|
+
throw new Error("project_id not found in service account file.");
|
|
80
|
+
}
|
|
78
81
|
return sa.project_id;
|
|
79
82
|
}
|
|
80
83
|
|
|
@@ -57,11 +57,14 @@ export async function deleteUserSubcollection(
|
|
|
57
57
|
const subcollectionSnapshot = await subcollectionRef.get();
|
|
58
58
|
|
|
59
59
|
if (!subcollectionSnapshot.empty) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
for (let i = 0; i < subcollectionSnapshot.docs.length; i += BATCH_SIZE) {
|
|
61
|
+
const chunk = subcollectionSnapshot.docs.slice(i, i + BATCH_SIZE);
|
|
62
|
+
const batch = db.batch();
|
|
63
|
+
chunk.forEach((doc) => batch.delete(doc.ref));
|
|
64
|
+
await batch.commit();
|
|
65
|
+
totalDeleted += chunk.length;
|
|
66
|
+
onProgress?.(totalDeleted);
|
|
67
|
+
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
|
|
@@ -88,10 +91,13 @@ export async function deleteAllData(
|
|
|
88
91
|
for (const subcollection of subcollections) {
|
|
89
92
|
const subSnapshot = await subcollection.get();
|
|
90
93
|
if (!subSnapshot.empty) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
for (let i = 0; i < subSnapshot.docs.length; i += BATCH_SIZE) {
|
|
95
|
+
const chunk = subSnapshot.docs.slice(i, i + BATCH_SIZE);
|
|
96
|
+
const batch = db.batch();
|
|
97
|
+
chunk.forEach((subDoc) => batch.delete(subDoc.ref));
|
|
98
|
+
await batch.commit();
|
|
99
|
+
totalDeleted += chunk.length;
|
|
100
|
+
}
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
}
|
|
@@ -99,10 +105,13 @@ export async function deleteAllData(
|
|
|
99
105
|
|
|
100
106
|
// Delete main collection documents
|
|
101
107
|
if (!snapshot.empty) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
for (let i = 0; i < snapshot.docs.length; i += BATCH_SIZE) {
|
|
109
|
+
const chunk = snapshot.docs.slice(i, i + BATCH_SIZE);
|
|
110
|
+
const batch = db.batch();
|
|
111
|
+
chunk.forEach((doc) => batch.delete(doc.ref));
|
|
112
|
+
await batch.commit();
|
|
113
|
+
totalDeleted += chunk.length;
|
|
114
|
+
}
|
|
106
115
|
onProgress?.(collection.id, totalDeleted);
|
|
107
116
|
}
|
|
108
117
|
}
|
|
@@ -61,26 +61,29 @@ export async function seedUserSubcollection(
|
|
|
61
61
|
errors: [],
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
for (let i = 0; i < docs.length; i += BATCH_SIZE) {
|
|
65
|
+
const slice = docs.slice(i, i + BATCH_SIZE);
|
|
66
|
+
const batch = db.batch();
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
for (const { id, data } of slice) {
|
|
69
|
+
const ref = db
|
|
70
|
+
.collection("users")
|
|
71
|
+
.doc(userId)
|
|
72
|
+
.collection(subcollectionName)
|
|
73
|
+
.doc(id);
|
|
74
|
+
const clean = Object.fromEntries(
|
|
75
|
+
Object.entries(data).filter(([, v]) => v !== undefined)
|
|
76
|
+
);
|
|
77
|
+
batch.set(ref, clean);
|
|
78
|
+
}
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
try {
|
|
81
|
+
await batch.commit();
|
|
82
|
+
result.processed += slice.length;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
result.success = false;
|
|
85
|
+
result.errors.push(`Failed to seed subcollection at index ${i}: ${error}`);
|
|
86
|
+
}
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
return result;
|
package/scripts/init.ts
CHANGED
|
@@ -56,6 +56,9 @@ export function getStorageAdmin(app: admin.app.App): admin.storage.Storage {
|
|
|
56
56
|
/**
|
|
57
57
|
* Reset initialized app (for testing)
|
|
58
58
|
*/
|
|
59
|
-
export function resetFirebaseAdmin(): void {
|
|
60
|
-
initializedApp
|
|
59
|
+
export async function resetFirebaseAdmin(): Promise<void> {
|
|
60
|
+
if (initializedApp) {
|
|
61
|
+
await initializedApp.delete();
|
|
62
|
+
initializedApp = null;
|
|
63
|
+
}
|
|
61
64
|
}
|
package/scripts/user-commands.ts
CHANGED
|
@@ -55,16 +55,16 @@ export async function addUserCredits(
|
|
|
55
55
|
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
if (credits.text) {
|
|
58
|
+
if (credits.text !== undefined) {
|
|
59
59
|
updates.text = admin.firestore.FieldValue.increment(credits.text);
|
|
60
60
|
}
|
|
61
|
-
if (credits.image) {
|
|
61
|
+
if (credits.image !== undefined) {
|
|
62
62
|
updates.image = admin.firestore.FieldValue.increment(credits.image);
|
|
63
63
|
}
|
|
64
|
-
if (credits.video) {
|
|
64
|
+
if (credits.video !== undefined) {
|
|
65
65
|
updates.video = admin.firestore.FieldValue.increment(credits.video);
|
|
66
66
|
}
|
|
67
|
-
if (credits.audio) {
|
|
67
|
+
if (credits.audio !== undefined) {
|
|
68
68
|
updates.audio = admin.firestore.FieldValue.increment(credits.audio);
|
|
69
69
|
}
|
|
70
70
|
|
package/scripts/utils.ts
CHANGED
|
@@ -28,6 +28,7 @@ export function randomDate(daysAgo: number): Date {
|
|
|
28
28
|
* Get random item from array
|
|
29
29
|
*/
|
|
30
30
|
export function randomItem<T>(arr: T[]): T {
|
|
31
|
+
if (arr.length === 0) throw new Error("Cannot pick random item from empty array");
|
|
31
32
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -57,9 +58,10 @@ export function sleep(ms: number): Promise<void> {
|
|
|
57
58
|
*/
|
|
58
59
|
export function formatBytes(bytes: number): string {
|
|
59
60
|
if (bytes === 0) return "0 Bytes";
|
|
61
|
+
if (bytes < 0) return "-" + formatBytes(-bytes);
|
|
60
62
|
const k = 1024;
|
|
61
|
-
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
62
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
63
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
64
|
+
const i = Math.min(Math.floor(Math.log(bytes) / Math.log(k)), sizes.length - 1);
|
|
63
65
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* Defines the contract for Firebase client operations
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import type { FirebaseApp } from 'firebase/app';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Firebase Client Interface
|
|
12
12
|
* Defines the contract for Firebase client operations
|
|
13
|
-
*
|
|
14
|
-
* Note:
|
|
13
|
+
*
|
|
14
|
+
* Note:
|
|
15
15
|
* - Firebase Auth is now handled by @umituz/react-native-firebase-auth
|
|
16
16
|
* - Firestore is now handled by @umituz/react-native-firestore
|
|
17
17
|
*/
|
|
@@ -40,7 +40,3 @@ export interface IFirebaseClient {
|
|
|
40
40
|
reset(): void;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
@@ -25,7 +25,9 @@ export function toAnonymousUser(user: User): AnonymousUser {
|
|
|
25
25
|
return {
|
|
26
26
|
uid: user.uid,
|
|
27
27
|
isAnonymous: user.isAnonymous,
|
|
28
|
-
createdAt:
|
|
28
|
+
createdAt: user.metadata.creationTime
|
|
29
|
+
? new Date(user.metadata.creationTime).getTime()
|
|
30
|
+
: Date.now(),
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -39,6 +41,6 @@ export function isValidAnonymousUser(user: unknown): user is AnonymousUser {
|
|
|
39
41
|
'uid' in user &&
|
|
40
42
|
typeof user.uid === 'string' &&
|
|
41
43
|
'isAnonymous' in user &&
|
|
42
|
-
|
|
44
|
+
user.isAnonymous === true
|
|
43
45
|
);
|
|
44
46
|
}
|
package/src/auth/index.ts
CHANGED
|
@@ -120,13 +120,13 @@ export {
|
|
|
120
120
|
export type {
|
|
121
121
|
GoogleAuthConfig,
|
|
122
122
|
GoogleAuthResult,
|
|
123
|
-
} from './infrastructure/services/google-auth.
|
|
123
|
+
} from './infrastructure/services/google-auth.types';
|
|
124
124
|
|
|
125
125
|
export {
|
|
126
126
|
AppleAuthService,
|
|
127
127
|
appleAuthService,
|
|
128
128
|
} from './infrastructure/services/apple-auth.service';
|
|
129
|
-
export type { AppleAuthResult } from './infrastructure/services/apple-auth.
|
|
129
|
+
export type { AppleAuthResult } from './infrastructure/services/apple-auth.types';
|
|
130
130
|
|
|
131
131
|
// =============================================================================
|
|
132
132
|
// PRESENTATION LAYER - Hooks
|
|
@@ -25,6 +25,9 @@ class FirebaseAuthClientSingleton {
|
|
|
25
25
|
const app = getFirebaseApp();
|
|
26
26
|
if (!app) return null;
|
|
27
27
|
this.auth = FirebaseAuthInitializer.initialize(app, config);
|
|
28
|
+
if (!this.auth) {
|
|
29
|
+
this.initializationError = "Auth initialization returned null";
|
|
30
|
+
}
|
|
28
31
|
return this.auth;
|
|
29
32
|
} catch (error: unknown) {
|
|
30
33
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -9,19 +9,12 @@ import {
|
|
|
9
9
|
reauthenticateWithApple,
|
|
10
10
|
reauthenticateWithPassword,
|
|
11
11
|
reauthenticateWithGoogle,
|
|
12
|
+
toAuthError,
|
|
12
13
|
} from "./reauthentication.service";
|
|
13
14
|
import type { AccountDeletionResult, AccountDeletionOptions } from "./reauthentication.types";
|
|
14
15
|
|
|
15
16
|
export type { AccountDeletionResult, AccountDeletionOptions } from "./reauthentication.types";
|
|
16
17
|
|
|
17
|
-
function toAuthError(error: unknown): { code: string; message: string } {
|
|
18
|
-
const err = error as { code?: string; message?: string };
|
|
19
|
-
return {
|
|
20
|
-
code: err.code || "auth/failed",
|
|
21
|
-
message: err.message || "Unknown error",
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
18
|
export async function deleteCurrentUser(
|
|
26
19
|
options: AccountDeletionOptions = { autoReauthenticate: true }
|
|
27
20
|
): Promise<AccountDeletionResult> {
|
|
@@ -78,7 +71,7 @@ async function attemptReauth(user: User, options: AccountDeletionOptions): Promi
|
|
|
78
71
|
return { success: false, error: { code: res.error?.code || "auth/reauth-failed", message: res.error?.message || "Reauth failed", requiresReauth: true } };
|
|
79
72
|
}
|
|
80
73
|
|
|
81
|
-
export async function deleteUserAccount(user: User): Promise<AccountDeletionResult> {
|
|
74
|
+
export async function deleteUserAccount(user: User | null): Promise<AccountDeletionResult> {
|
|
82
75
|
if (!user || user.isAnonymous) return { success: false, error: { code: "auth/invalid", message: "Invalid user", requiresReauth: false } };
|
|
83
76
|
try {
|
|
84
77
|
await deleteUser(user);
|
|
@@ -22,7 +22,7 @@ export class AnonymousAuthService implements AnonymousAuthServiceInterface {
|
|
|
22
22
|
|
|
23
23
|
const currentUser = auth.currentUser;
|
|
24
24
|
|
|
25
|
-
if (currentUser) {
|
|
25
|
+
if (currentUser && currentUser.isAnonymous) {
|
|
26
26
|
return {
|
|
27
27
|
user: currentUser,
|
|
28
28
|
anonymousUser: toAnonymousUser(currentUser),
|
|
@@ -30,6 +30,10 @@ export class AnonymousAuthService implements AnonymousAuthServiceInterface {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
if (currentUser && !currentUser.isAnonymous) {
|
|
34
|
+
throw new Error("A non-anonymous user is already signed in. Sign out first before creating an anonymous session.");
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
try {
|
|
34
38
|
const userCredential = await signInAnonymously(auth);
|
|
35
39
|
const anonymousUser = toAnonymousUser(userCredential.user);
|
|
@@ -7,18 +7,11 @@ import {
|
|
|
7
7
|
OAuthProvider,
|
|
8
8
|
signInWithCredential,
|
|
9
9
|
type Auth,
|
|
10
|
-
type UserCredential,
|
|
11
10
|
} from "firebase/auth";
|
|
12
11
|
import * as AppleAuthentication from "expo-apple-authentication";
|
|
13
12
|
import { Platform } from "react-native";
|
|
14
13
|
import { generateNonce, hashNonce } from "./crypto.util";
|
|
15
|
-
|
|
16
|
-
export interface AppleAuthResult {
|
|
17
|
-
success: boolean;
|
|
18
|
-
userCredential?: UserCredential;
|
|
19
|
-
error?: string;
|
|
20
|
-
isNewUser?: boolean;
|
|
21
|
-
}
|
|
14
|
+
import type { AppleAuthResult } from "./apple-auth.types";
|
|
22
15
|
|
|
23
16
|
export class AppleAuthService {
|
|
24
17
|
async isAvailable(): Promise<boolean> {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Auth, User } from 'firebase/auth';
|
|
9
9
|
import { getFirebaseAuth } from '../config/FirebaseAuthClient';
|
|
10
|
+
import { userToAuthCheckResult } from '../../presentation/hooks/utils/auth-state-change.handler';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Auth check result interface
|
|
@@ -24,22 +25,7 @@ export interface AuthCheckResult {
|
|
|
24
25
|
* Optimized: Single traversal of auth state
|
|
25
26
|
*/
|
|
26
27
|
export function checkAuthState(auth: Auth | null): AuthCheckResult {
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
isAuthenticated: false,
|
|
30
|
-
isAnonymous: false,
|
|
31
|
-
currentUser: null,
|
|
32
|
-
userId: null,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const currentUser = auth.currentUser;
|
|
37
|
-
return {
|
|
38
|
-
isAuthenticated: true,
|
|
39
|
-
isAnonymous: currentUser.isAnonymous === true,
|
|
40
|
-
currentUser,
|
|
41
|
-
userId: currentUser.uid,
|
|
42
|
-
};
|
|
28
|
+
return userToAuthCheckResult(auth?.currentUser ?? null);
|
|
43
29
|
}
|
|
44
30
|
|
|
45
31
|
/**
|
|
@@ -116,6 +102,6 @@ export function verifyUserId(auth: Auth | null, userId: string): boolean {
|
|
|
116
102
|
* Check if user exists and is valid
|
|
117
103
|
*/
|
|
118
104
|
export function isValidUser(user: User | null | undefined): user is User {
|
|
119
|
-
return user
|
|
105
|
+
return !!user && typeof user.uid === 'string' && user.uid.length > 0;
|
|
120
106
|
}
|
|
121
107
|
|
|
@@ -7,27 +7,8 @@ import {
|
|
|
7
7
|
GoogleAuthProvider,
|
|
8
8
|
signInWithCredential,
|
|
9
9
|
type Auth,
|
|
10
|
-
type UserCredential,
|
|
11
10
|
} from "firebase/auth";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Google Auth configuration
|
|
15
|
-
*/
|
|
16
|
-
export interface GoogleAuthConfig {
|
|
17
|
-
webClientId?: string;
|
|
18
|
-
iosClientId?: string;
|
|
19
|
-
androidClientId?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Google Auth result
|
|
24
|
-
*/
|
|
25
|
-
export interface GoogleAuthResult {
|
|
26
|
-
success: boolean;
|
|
27
|
-
userCredential?: UserCredential;
|
|
28
|
-
error?: string;
|
|
29
|
-
isNewUser?: boolean;
|
|
30
|
-
}
|
|
11
|
+
import type { GoogleAuthConfig, GoogleAuthResult } from "./google-auth.types";
|
|
31
12
|
|
|
32
13
|
/**
|
|
33
14
|
* Google Auth Service
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google Auth Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { UserCredential } from "firebase/auth";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Google Auth configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface GoogleAuthConfig {
|
|
11
|
+
webClientId?: string;
|
|
12
|
+
iosClientId?: string;
|
|
13
|
+
androidClientId?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Google Auth result
|
|
18
|
+
*/
|
|
19
|
+
export interface GoogleAuthResult {
|
|
20
|
+
success: boolean;
|
|
21
|
+
userCredential?: UserCredential;
|
|
22
|
+
error?: string;
|
|
23
|
+
isNewUser?: boolean;
|
|
24
|
+
}
|
|
@@ -25,11 +25,17 @@ export type {
|
|
|
25
25
|
ReauthCredentialResult
|
|
26
26
|
} from "./reauthentication.types";
|
|
27
27
|
|
|
28
|
-
function toAuthError(error: unknown): { code: string; message: string } {
|
|
29
|
-
|
|
28
|
+
export function toAuthError(error: unknown): { code: string; message: string } {
|
|
29
|
+
if (error instanceof Error) {
|
|
30
|
+
const firebaseErr = error as { code?: string };
|
|
31
|
+
return {
|
|
32
|
+
code: firebaseErr.code || "auth/failed",
|
|
33
|
+
message: error.message,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
30
36
|
return {
|
|
31
|
-
code:
|
|
32
|
-
message:
|
|
37
|
+
code: "auth/failed",
|
|
38
|
+
message: typeof error === 'string' ? error : "Unknown error",
|
|
33
39
|
};
|
|
34
40
|
}
|
|
35
41
|
|
|
@@ -5,10 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
import { useState, useCallback, useEffect } from "react";
|
|
7
7
|
import { getFirebaseAuth } from "../../infrastructure/config/FirebaseAuthClient";
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
type GoogleAuthConfig,
|
|
11
|
-
} from "../../infrastructure/services/google-auth.service";
|
|
8
|
+
import { googleAuthService } from "../../infrastructure/services/google-auth.service";
|
|
9
|
+
import type { GoogleAuthConfig } from "../../infrastructure/services/google-auth.types";
|
|
12
10
|
import { appleAuthService } from "../../infrastructure/services/apple-auth.service";
|
|
13
11
|
|
|
14
12
|
export interface SocialAuthConfig {
|
|
@@ -31,20 +29,6 @@ export interface UseSocialAuthResult {
|
|
|
31
29
|
appleAvailable: boolean;
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
/**
|
|
35
|
-
* Common sign-in wrapper
|
|
36
|
-
*/
|
|
37
|
-
async function signInWrapper(
|
|
38
|
-
signInFn: () => Promise<{ success: boolean; isNewUser?: boolean; error?: string }>
|
|
39
|
-
): Promise<SocialAuthResult> {
|
|
40
|
-
const auth = getFirebaseAuth();
|
|
41
|
-
if (!auth) {
|
|
42
|
-
return { success: false, error: "Firebase Auth not initialized" };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return signInFn();
|
|
46
|
-
}
|
|
47
|
-
|
|
48
32
|
export function useSocialAuth(config?: SocialAuthConfig): UseSocialAuthResult {
|
|
49
33
|
const [googleLoading, setGoogleLoading] = useState(false);
|
|
50
34
|
const [appleLoading, setAppleLoading] = useState(false);
|
|
@@ -81,9 +65,7 @@ export function useSocialAuth(config?: SocialAuthConfig): UseSocialAuthResult {
|
|
|
81
65
|
try {
|
|
82
66
|
const auth = getFirebaseAuth();
|
|
83
67
|
if (!auth) return { success: false, error: "Firebase Auth not initialized" };
|
|
84
|
-
return await
|
|
85
|
-
googleAuthService.signInWithIdToken(auth, idToken)
|
|
86
|
-
);
|
|
68
|
+
return await googleAuthService.signInWithIdToken(auth, idToken);
|
|
87
69
|
} catch (error) {
|
|
88
70
|
return {
|
|
89
71
|
success: false,
|
|
@@ -105,9 +87,7 @@ export function useSocialAuth(config?: SocialAuthConfig): UseSocialAuthResult {
|
|
|
105
87
|
try {
|
|
106
88
|
const auth = getFirebaseAuth();
|
|
107
89
|
if (!auth) return { success: false, error: "Firebase Auth not initialized" };
|
|
108
|
-
return await
|
|
109
|
-
appleAuthService.signIn(auth)
|
|
110
|
-
);
|
|
90
|
+
return await appleAuthService.signIn(auth);
|
|
111
91
|
} catch (error) {
|
|
112
92
|
return {
|
|
113
93
|
success: false,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { QuotaMetrics, QuotaLimits, QuotaStatus } from '../entities/QuotaMetrics';
|
|
7
|
-
import { FREE_TIER_LIMITS } from '../constants/QuotaLimits';
|
|
7
|
+
import { FREE_TIER_LIMITS, QUOTA_THRESHOLDS, calculateQuotaUsage } from '../constants/QuotaLimits';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Default quota limits (Firebase Spark Plan)
|
|
@@ -24,14 +24,15 @@ export class QuotaCalculator {
|
|
|
24
24
|
metrics: QuotaMetrics,
|
|
25
25
|
limits: QuotaLimits = DEFAULT_QUOTA_LIMITS,
|
|
26
26
|
): QuotaStatus {
|
|
27
|
-
const readPercentage = (metrics.readCount
|
|
28
|
-
const writePercentage = (metrics.writeCount
|
|
29
|
-
const deletePercentage = (metrics.deleteCount
|
|
27
|
+
const readPercentage = calculateQuotaUsage(metrics.readCount, limits.dailyReadLimit) * 100;
|
|
28
|
+
const writePercentage = calculateQuotaUsage(metrics.writeCount, limits.dailyWriteLimit) * 100;
|
|
29
|
+
const deletePercentage = calculateQuotaUsage(metrics.deleteCount, limits.dailyDeleteLimit) * 100;
|
|
30
30
|
|
|
31
|
+
const warningThreshold = QUOTA_THRESHOLDS.WARNING * 100;
|
|
31
32
|
const isNearLimit =
|
|
32
|
-
readPercentage >=
|
|
33
|
-
writePercentage >=
|
|
34
|
-
deletePercentage >=
|
|
33
|
+
readPercentage >= warningThreshold ||
|
|
34
|
+
writePercentage >= warningThreshold ||
|
|
35
|
+
deletePercentage >= warningThreshold;
|
|
35
36
|
|
|
36
37
|
const isOverLimit =
|
|
37
38
|
readPercentage >= 100 ||
|
|
@@ -22,27 +22,27 @@ export class QuotaTrackingMiddleware {
|
|
|
22
22
|
info: OperationInfo,
|
|
23
23
|
operation: () => Promise<T>
|
|
24
24
|
): Promise<T> {
|
|
25
|
-
|
|
25
|
+
try {
|
|
26
|
+
return await operation();
|
|
27
|
+
} finally {
|
|
28
|
+
switch (info.type) {
|
|
29
|
+
case 'read':
|
|
30
|
+
if (!info.cached) {
|
|
31
|
+
this.readCount += info.count;
|
|
32
|
+
}
|
|
33
|
+
break;
|
|
34
|
+
case 'write':
|
|
35
|
+
this.writeCount += info.count;
|
|
36
|
+
break;
|
|
37
|
+
case 'delete':
|
|
38
|
+
this.deleteCount += info.count;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
26
41
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.readCount += info.count;
|
|
31
|
-
}
|
|
32
|
-
break;
|
|
33
|
-
case 'write':
|
|
34
|
-
this.writeCount += info.count;
|
|
35
|
-
break;
|
|
36
|
-
case 'delete':
|
|
37
|
-
this.deleteCount += info.count;
|
|
38
|
-
break;
|
|
42
|
+
if (__DEV__) {
|
|
43
|
+
console.log(`[QuotaTracking] ${info.type}: ${info.collection} (${info.count})`);
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
|
-
|
|
41
|
-
if (__DEV__) {
|
|
42
|
-
console.log(`[QuotaTracking] ${info.type}: ${info.collection} (${info.count})`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return result;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
@@ -60,7 +60,7 @@ export class QuotaTrackingMiddleware {
|
|
|
60
60
|
/**
|
|
61
61
|
* Track write operation
|
|
62
62
|
*/
|
|
63
|
-
trackWrite(collection: string,
|
|
63
|
+
trackWrite(collection: string, count: number = 1): void {
|
|
64
64
|
this.writeCount += count;
|
|
65
65
|
if (__DEV__) {
|
|
66
66
|
console.log(`[QuotaTracking] write: ${collection} (${count})`);
|
|
@@ -70,7 +70,7 @@ export class QuotaTrackingMiddleware {
|
|
|
70
70
|
/**
|
|
71
71
|
* Track delete operation
|
|
72
72
|
*/
|
|
73
|
-
trackDelete(collection: string,
|
|
73
|
+
trackDelete(collection: string, count: number = 1): void {
|
|
74
74
|
this.deleteCount += count;
|
|
75
75
|
if (__DEV__) {
|
|
76
76
|
console.log(`[QuotaTracking] delete: ${collection} (${count})`);
|
|
@@ -54,7 +54,7 @@ export abstract class BaseQueryRepository extends BaseRepository {
|
|
|
54
54
|
* @param count - Number of documents read
|
|
55
55
|
* @param cached - Whether the result is from cache
|
|
56
56
|
*/
|
|
57
|
-
protected
|
|
57
|
+
protected trackRead(
|
|
58
58
|
collection: string,
|
|
59
59
|
count: number = 1,
|
|
60
60
|
cached: boolean = false,
|
|
@@ -62,19 +62,17 @@ export abstract class BaseQueryRepository extends BaseRepository {
|
|
|
62
62
|
quotaTrackingMiddleware.trackRead(collection, count, cached);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
protected
|
|
65
|
+
protected trackWrite(
|
|
66
66
|
collection: string,
|
|
67
|
-
documentId?: string,
|
|
68
67
|
count: number = 1,
|
|
69
68
|
): void {
|
|
70
|
-
quotaTrackingMiddleware.trackWrite(collection,
|
|
69
|
+
quotaTrackingMiddleware.trackWrite(collection, count);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
protected
|
|
72
|
+
protected trackDelete(
|
|
74
73
|
collection: string,
|
|
75
|
-
documentId?: string,
|
|
76
74
|
count: number = 1,
|
|
77
75
|
): void {
|
|
78
|
-
quotaTrackingMiddleware.trackDelete(collection,
|
|
76
|
+
quotaTrackingMiddleware.trackDelete(collection, count);
|
|
79
77
|
}
|
|
80
78
|
}
|
|
@@ -53,6 +53,9 @@ export class BaseRepository {
|
|
|
53
53
|
* @throws Error if Firestore is not initialized
|
|
54
54
|
*/
|
|
55
55
|
protected getDbOrThrow(): Firestore {
|
|
56
|
+
if (this.isDestroyed) {
|
|
57
|
+
throw new Error("Repository has been destroyed");
|
|
58
|
+
}
|
|
56
59
|
const db = getFirestore();
|
|
57
60
|
if (!db) {
|
|
58
61
|
throw new Error("Firestore is not initialized. Please initialize Firebase App first.");
|
|
@@ -120,24 +123,6 @@ export class BaseRepository {
|
|
|
120
123
|
}
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
/**
|
|
124
|
-
* Track read operations (stub for analytics)
|
|
125
|
-
* @param collection - Collection name
|
|
126
|
-
* @param count - Number of reads
|
|
127
|
-
* @param cached - Whether read was from cache
|
|
128
|
-
*/
|
|
129
|
-
protected trackRead(_collection: string, _count: number, _cached: boolean): void {
|
|
130
|
-
// Stub for future analytics implementation
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
protected trackWrite(_collection: string, _docId: string, _count: number): void {
|
|
134
|
-
// Stub for future analytics implementation
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
protected trackDelete(_collection: string, _docId: string, _count: number): void {
|
|
138
|
-
// Stub for future analytics implementation
|
|
139
|
-
}
|
|
140
|
-
|
|
141
126
|
/**
|
|
142
127
|
* Destroy repository and cleanup resources
|
|
143
128
|
*/
|
|
@@ -4,22 +4,28 @@ import { Timestamp } from 'firebase/firestore';
|
|
|
4
4
|
* Convert ISO string to Firestore Timestamp
|
|
5
5
|
*/
|
|
6
6
|
export function isoToTimestamp(isoString: string): Timestamp {
|
|
7
|
-
|
|
7
|
+
const date = new Date(isoString);
|
|
8
|
+
if (isNaN(date.getTime())) {
|
|
9
|
+
throw new Error(`Invalid ISO date string: ${isoString}`);
|
|
10
|
+
}
|
|
11
|
+
return Timestamp.fromDate(date);
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
/**
|
|
11
15
|
* Convert Firestore Timestamp to ISO string
|
|
16
|
+
* Returns null if timestamp is null or undefined
|
|
12
17
|
*/
|
|
13
|
-
export function timestampToISO(timestamp: Timestamp | null | undefined): string {
|
|
14
|
-
if (!timestamp) return
|
|
18
|
+
export function timestampToISO(timestamp: Timestamp | null | undefined): string | null {
|
|
19
|
+
if (!timestamp) return null;
|
|
15
20
|
return timestamp.toDate().toISOString();
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* Convert Firestore Timestamp to Date
|
|
25
|
+
* Returns null if timestamp is null or undefined
|
|
20
26
|
*/
|
|
21
|
-
export function timestampToDate(timestamp: Timestamp | null | undefined): Date {
|
|
22
|
-
if (!timestamp) return
|
|
27
|
+
export function timestampToDate(timestamp: Timestamp | null | undefined): Date | null {
|
|
28
|
+
if (!timestamp) return null;
|
|
23
29
|
return timestamp.toDate();
|
|
24
30
|
}
|
|
25
31
|
|
|
@@ -9,9 +9,10 @@ const QUOTA_ERROR_CODES = [
|
|
|
9
9
|
];
|
|
10
10
|
|
|
11
11
|
const QUOTA_ERROR_MESSAGES = [
|
|
12
|
-
'quota',
|
|
13
|
-
'
|
|
14
|
-
'limit',
|
|
12
|
+
'quota exceeded',
|
|
13
|
+
'quota limit',
|
|
14
|
+
'daily limit',
|
|
15
|
+
'resource exhausted',
|
|
15
16
|
'too many requests',
|
|
16
17
|
];
|
|
17
18
|
|
|
@@ -19,11 +20,14 @@ const QUOTA_ERROR_MESSAGES = [
|
|
|
19
20
|
* Check if error is a Firestore quota error
|
|
20
21
|
*/
|
|
21
22
|
export function isQuotaError(error: unknown): boolean {
|
|
22
|
-
if (!error) return false;
|
|
23
|
+
if (!error || typeof error !== 'object') return false;
|
|
23
24
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const code = 'code' in error && typeof (error as Record<string, unknown>).code === 'string'
|
|
26
|
+
? (error as Record<string, unknown>).code as string
|
|
27
|
+
: undefined;
|
|
28
|
+
const message = 'message' in error && typeof (error as Record<string, unknown>).message === 'string'
|
|
29
|
+
? (error as Record<string, unknown>).message as string
|
|
30
|
+
: undefined;
|
|
27
31
|
|
|
28
32
|
if (code && QUOTA_ERROR_CODES.some((c) => code.includes(c))) {
|
|
29
33
|
return true;
|
|
@@ -41,10 +45,11 @@ export function isQuotaError(error: unknown): boolean {
|
|
|
41
45
|
* Check if error is retryable
|
|
42
46
|
*/
|
|
43
47
|
export function isRetryableError(error: unknown): boolean {
|
|
44
|
-
if (!error) return false;
|
|
48
|
+
if (!error || typeof error !== 'object') return false;
|
|
45
49
|
|
|
46
|
-
const
|
|
47
|
-
|
|
50
|
+
const code = 'code' in error && typeof (error as Record<string, unknown>).code === 'string'
|
|
51
|
+
? (error as Record<string, unknown>).code as string
|
|
52
|
+
: undefined;
|
|
48
53
|
|
|
49
54
|
const retryableCodes = ['unavailable', 'deadline-exceeded', 'aborted'];
|
|
50
55
|
|
package/src/index.ts
CHANGED
|
@@ -73,7 +73,7 @@ export { anonymousAuthService } from "./auth/infrastructure/services/anonymous-a
|
|
|
73
73
|
export { deleteCurrentUser } from "./auth/infrastructure/services/account-deletion.service";
|
|
74
74
|
export { appleAuthService } from "./auth/infrastructure/services/apple-auth.service";
|
|
75
75
|
export { googleAuthService } from "./auth/infrastructure/services/google-auth.service";
|
|
76
|
-
export type { GoogleAuthConfig } from "./auth/infrastructure/services/google-auth.
|
|
76
|
+
export type { GoogleAuthConfig } from "./auth/infrastructure/services/google-auth.types";
|
|
77
77
|
export { useAnonymousAuth } from "./auth/presentation/hooks/useAnonymousAuth";
|
|
78
78
|
export type { UseAnonymousAuthResult } from "./auth/presentation/hooks/useAnonymousAuth";
|
|
79
79
|
|
|
@@ -76,7 +76,7 @@ export function loadFirebaseConfig(): FirebaseConfig | null {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
// Validate required fields
|
|
79
|
-
if (!config.apiKey?.trim() || !config.projectId?.trim()) {
|
|
79
|
+
if (!config.apiKey?.trim() || !config.authDomain?.trim() || !config.projectId?.trim()) {
|
|
80
80
|
return null;
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -29,7 +29,7 @@ export class FirebaseServiceInitializer {
|
|
|
29
29
|
let auth: unknown = null;
|
|
30
30
|
if (options?.authInitializer) {
|
|
31
31
|
try {
|
|
32
|
-
auth = options.authInitializer();
|
|
32
|
+
auth = await options.authInitializer();
|
|
33
33
|
if (__DEV__) {
|
|
34
34
|
console.log('[Firebase] Auth initialized via callback');
|
|
35
35
|
}
|
package/src/storage/types.ts
CHANGED
package/src/storage/uploader.ts
CHANGED
|
@@ -16,9 +16,13 @@ import type { UploadResult, UploadOptions } from "./types";
|
|
|
16
16
|
* Extract MIME type from base64 data URL or return default
|
|
17
17
|
*/
|
|
18
18
|
export function getMimeType(base64: string): string {
|
|
19
|
+
if (base64.startsWith("data:image/jpeg") || base64.startsWith("data:image/jpg")) return "image/jpeg";
|
|
19
20
|
if (base64.startsWith("data:image/png")) return "image/png";
|
|
20
21
|
if (base64.startsWith("data:image/webp")) return "image/webp";
|
|
21
22
|
if (base64.startsWith("data:image/gif")) return "image/gif";
|
|
23
|
+
if (__DEV__) {
|
|
24
|
+
console.warn("[StorageUploader] Could not detect MIME type from base64 prefix, falling back to image/jpeg");
|
|
25
|
+
}
|
|
22
26
|
return "image/jpeg";
|
|
23
27
|
}
|
|
24
28
|
|
|
@@ -104,8 +108,12 @@ export async function uploadFile(
|
|
|
104
108
|
const response = await fetch(uri);
|
|
105
109
|
const blob = await response.blob();
|
|
106
110
|
|
|
111
|
+
const contentType = options?.mimeType ?? "image/jpeg";
|
|
112
|
+
if (!options?.mimeType && __DEV__) {
|
|
113
|
+
console.warn("[StorageUploader] No MIME type provided for file upload, falling back to image/jpeg");
|
|
114
|
+
}
|
|
107
115
|
const metadata: UploadMetadata = {
|
|
108
|
-
contentType
|
|
116
|
+
contentType,
|
|
109
117
|
customMetadata: options?.customMetadata,
|
|
110
118
|
};
|
|
111
119
|
|