@umituz/react-native-firebase 1.13.49 → 1.13.50

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/dist/scripts/cli-handlers.d.ts +27 -0
  2. package/dist/scripts/cli-handlers.d.ts.map +1 -0
  3. package/dist/scripts/cli-handlers.js +125 -0
  4. package/dist/scripts/cli-handlers.js.map +1 -0
  5. package/dist/scripts/cli-parser.d.ts +25 -0
  6. package/dist/scripts/cli-parser.d.ts.map +1 -0
  7. package/dist/scripts/cli-parser.js +101 -0
  8. package/dist/scripts/cli-parser.js.map +1 -0
  9. package/dist/scripts/cli.js +20 -155
  10. package/dist/scripts/cli.js.map +1 -1
  11. package/dist/scripts/firestore-operations.d.ts +18 -0
  12. package/dist/scripts/firestore-operations.d.ts.map +1 -0
  13. package/dist/scripts/firestore-operations.js +88 -0
  14. package/dist/scripts/firestore-operations.js.map +1 -0
  15. package/dist/scripts/firestore-queries.d.ts +27 -0
  16. package/dist/scripts/firestore-queries.d.ts.map +1 -0
  17. package/dist/scripts/firestore-queries.js +77 -0
  18. package/dist/scripts/firestore-queries.js.map +1 -0
  19. package/dist/scripts/firestore-seeding.d.ts +21 -0
  20. package/dist/scripts/firestore-seeding.d.ts.map +1 -0
  21. package/dist/scripts/firestore-seeding.js +67 -0
  22. package/dist/scripts/firestore-seeding.js.map +1 -0
  23. package/dist/scripts/firestore.d.ts +3 -48
  24. package/dist/scripts/firestore.d.ts.map +1 -1
  25. package/dist/scripts/firestore.js +16 -210
  26. package/dist/scripts/firestore.js.map +1 -1
  27. package/dist/scripts/user-commands.d.ts +33 -0
  28. package/dist/scripts/user-commands.d.ts.map +1 -0
  29. package/dist/scripts/user-commands.js +113 -0
  30. package/dist/scripts/user-commands.js.map +1 -0
  31. package/dist/scripts/user-formatters.d.ts +10 -0
  32. package/dist/scripts/user-formatters.d.ts.map +1 -0
  33. package/dist/scripts/user-formatters.js +55 -0
  34. package/dist/scripts/user-formatters.js.map +1 -0
  35. package/dist/scripts/user-queries.d.ts +42 -0
  36. package/dist/scripts/user-queries.d.ts.map +1 -0
  37. package/dist/scripts/user-queries.js +125 -0
  38. package/dist/scripts/user-queries.js.map +1 -0
  39. package/dist/scripts/user.d.ts +3 -67
  40. package/dist/scripts/user.d.ts.map +1 -1
  41. package/dist/scripts/user.js +15 -272
  42. package/dist/scripts/user.js.map +1 -1
  43. package/package.json +1 -1
  44. package/scripts/cli-handlers.ts +170 -0
  45. package/scripts/cli-parser.ts +82 -0
  46. package/scripts/cli.ts +27 -193
  47. package/scripts/firestore-operations.ts +111 -0
  48. package/scripts/firestore-queries.ts +97 -0
  49. package/scripts/firestore-seeding.ts +87 -0
  50. package/scripts/firestore.ts +20 -275
  51. package/scripts/user-commands.ts +104 -0
  52. package/scripts/user-formatters.ts +55 -0
  53. package/scripts/user-queries.ts +185 -0
  54. package/scripts/user.ts +19 -326
package/scripts/cli.ts CHANGED
@@ -22,90 +22,22 @@
22
22
  */
23
23
 
24
24
  import * as path from "path";
25
- import * as fs from "fs";
26
25
  import {
27
26
  initFirebaseAdmin,
28
27
  getFirestoreAdmin,
29
28
  resetFirebaseAdmin,
30
29
  } from "./init";
30
+ import { parseArgs, getProjectId } from "./cli-parser";
31
31
  import {
32
- getUserData,
33
- initializeUserCredits,
34
- setUserCredits,
35
- listUsersWithCredits,
36
- getCreditsSummary,
37
- printUserData,
38
- } from "./user";
39
- import { printHeader, printSeparator } from "./utils";
40
-
41
- interface CLIOptions {
42
- serviceAccountPath: string;
43
- projectId?: string;
44
- creditsCollection: string;
45
- textLimit: number;
46
- imageLimit: number;
47
- }
48
-
49
- function parseArgs(): { command: string; args: string[]; options: CLIOptions } {
50
- const args = process.argv.slice(2);
51
- const command = args[0] || "help";
52
- const commandArgs: string[] = [];
53
- const options: CLIOptions = {
54
- serviceAccountPath: "./firebase-service-account.json",
55
- creditsCollection: "user_credits",
56
- textLimit: 100,
57
- imageLimit: 100,
58
- };
59
-
60
- let i = 1;
61
- while (i < args.length) {
62
- const arg = args[i];
63
- if (arg.startsWith("--")) {
64
- const key = arg.slice(2);
65
- const value = args[++i];
66
- switch (key) {
67
- case "service-account":
68
- options.serviceAccountPath = value;
69
- break;
70
- case "project-id":
71
- options.projectId = value;
72
- break;
73
- case "credits-collection":
74
- options.creditsCollection = value;
75
- break;
76
- case "text-limit":
77
- options.textLimit = parseInt(value) || 100;
78
- break;
79
- case "image-limit":
80
- options.imageLimit = parseInt(value) || 100;
81
- break;
82
- }
83
- } else {
84
- commandArgs.push(arg);
85
- }
86
- i++;
87
- }
88
-
89
- return { command, args: commandArgs, options };
90
- }
91
-
92
- function getProjectId(options: CLIOptions): string {
93
- if (options.projectId) return options.projectId;
94
-
95
- const saPath = path.resolve(process.cwd(), options.serviceAccountPath);
96
- if (fs.existsSync(saPath)) {
97
- const sa = JSON.parse(fs.readFileSync(saPath, "utf8"));
98
- return sa.project_id;
99
- }
100
-
101
- throw new Error("Project ID not found. Use --project-id or ensure service account file exists.");
102
- }
103
-
104
- async function main() {
105
- const { command, args, options } = parseArgs();
106
-
107
- if (command === "help") {
108
- console.log(`
32
+ handleReadUser,
33
+ handleInitCredits,
34
+ handleSetCredits,
35
+ handleListUsers,
36
+ handleCreditsSummary,
37
+ } from "./cli-handlers";
38
+
39
+ function printHelp(): void {
40
+ console.log(`
109
41
  Firebase Admin CLI
110
42
 
111
43
  Commands:
@@ -129,6 +61,13 @@ Examples:
129
61
  npx ts-node cli.ts list-users --limit 50
130
62
  npx ts-node cli.ts credits-summary
131
63
  `);
64
+ }
65
+
66
+ async function main() {
67
+ const { command, args, options } = parseArgs();
68
+
69
+ if (command === "help") {
70
+ printHelp();
132
71
  process.exit(0);
133
72
  }
134
73
 
@@ -144,130 +83,25 @@ Examples:
144
83
  const db = getFirestoreAdmin(app);
145
84
 
146
85
  switch (command) {
147
- case "read-user": {
148
- const userId = args[0];
149
- if (!userId) {
150
- console.error("❌ Error: userId is required");
151
- process.exit(1);
152
- }
153
-
154
- printHeader(`📖 READ USER: ${userId}`);
155
- const userData = await getUserData(db, userId, {
156
- creditsCollection: options.creditsCollection,
157
- });
158
- printUserData(userData);
86
+ case "read-user":
87
+ await handleReadUser(db, args, options);
159
88
  break;
160
- }
161
-
162
- case "init-credits": {
163
- const userId = args[0];
164
- if (!userId) {
165
- console.error("❌ Error: userId is required");
166
- process.exit(1);
167
- }
168
-
169
- printHeader(`💰 INIT CREDITS: ${userId}`);
170
- console.log(`Collection: ${options.creditsCollection}`);
171
- console.log(`Limits: Text=${options.textLimit}, Image=${options.imageLimit}\n`);
172
-
173
- const existing = await getUserData(db, userId, {
174
- creditsCollection: options.creditsCollection,
175
- });
176
-
177
- if (existing.credits) {
178
- console.log("⚠️ Credits already exist:");
179
- console.log(` Text: ${existing.credits.text}`);
180
- console.log(` Image: ${existing.credits.image}`);
181
- console.log("\n Use 'set-credits' to overwrite.");
182
- break;
183
- }
184
-
185
- const credits = await initializeUserCredits(db, userId, {
186
- collectionName: options.creditsCollection,
187
- textLimit: options.textLimit,
188
- imageLimit: options.imageLimit,
189
- });
190
89
 
191
- console.log("✅ Credits initialized:");
192
- console.log(` Text: ${credits.text}`);
193
- console.log(` Image: ${credits.image}`);
90
+ case "init-credits":
91
+ await handleInitCredits(db, args, options);
194
92
  break;
195
- }
196
93
 
197
- case "set-credits": {
198
- const userId = args[0];
199
- const text = parseInt(args[1]);
200
- const image = parseInt(args[2]);
201
-
202
- if (!userId || isNaN(text) || isNaN(image)) {
203
- console.error("❌ Error: Usage: set-credits <userId> <text> <image>");
204
- process.exit(1);
205
- }
206
-
207
- printHeader(`💰 SET CREDITS: ${userId}`);
208
- console.log(`Setting: Text=${text}, Image=${image}\n`);
209
-
210
- await setUserCredits(db, userId, { text, image }, options.creditsCollection);
211
-
212
- console.log("✅ Credits set successfully!");
213
-
214
- const updated = await getUserData(db, userId, {
215
- creditsCollection: options.creditsCollection,
216
- });
217
- printUserData(updated);
94
+ case "set-credits":
95
+ await handleSetCredits(db, args, options);
218
96
  break;
219
- }
220
97
 
221
- case "list-users": {
222
- const limit = parseInt(args[0]) || 100;
223
-
224
- printHeader("👥 USERS WITH CREDITS");
225
- const users = await listUsersWithCredits(db, {
226
- creditsCollection: options.creditsCollection,
227
- limit,
228
- });
229
-
230
- console.log(`Found ${users.length} users:\n`);
231
- printSeparator("-", 80);
232
- console.log(
233
- "ID".padEnd(30) +
234
- "Name".padEnd(20) +
235
- "Text".padEnd(10) +
236
- "Image".padEnd(10) +
237
- "Anon"
238
- );
239
- printSeparator("-", 80);
240
-
241
- users.forEach((u) => {
242
- const text = u.credits?.text ?? "-";
243
- const image = u.credits?.image ?? "-";
244
- console.log(
245
- u.userId.substring(0, 28).padEnd(30) +
246
- (u.displayName || "-").substring(0, 18).padEnd(20) +
247
- String(text).padEnd(10) +
248
- String(image).padEnd(10) +
249
- (u.isAnonymous ? "Yes" : "No")
250
- );
251
- });
252
- printSeparator("-", 80);
98
+ case "list-users":
99
+ await handleListUsers(db, args, options);
253
100
  break;
254
- }
255
-
256
- case "credits-summary": {
257
- printHeader("📊 CREDITS SUMMARY");
258
- const summary = await getCreditsSummary(db, options.creditsCollection);
259
101
 
260
- console.log(`Total Users: ${summary.totalUsers}`);
261
- console.log(`With Credits: ${summary.usersWithCredits}`);
262
- console.log(`Zero Credits: ${summary.usersWithZeroCredits}`);
263
- console.log();
264
- console.log("Total Credits Across All Users:");
265
- console.log(` Text: ${summary.totalText}`);
266
- console.log(` Image: ${summary.totalImage}`);
267
- console.log(` Video: ${summary.totalVideo}`);
268
- console.log(` Audio: ${summary.totalAudio}`);
102
+ case "credits-summary":
103
+ await handleCreditsSummary(db, options);
269
104
  break;
270
- }
271
105
 
272
106
  default:
273
107
  console.error(`❌ Unknown command: ${command}`);
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Firebase Admin Firestore Operations
3
+ * Delete operations for Firestore data
4
+ */
5
+
6
+ import * as admin from "firebase-admin";
7
+
8
+ const BATCH_SIZE = 500;
9
+
10
+ /**
11
+ * Delete collection in batches
12
+ */
13
+ export async function deleteCollection(
14
+ db: admin.firestore.Firestore,
15
+ collectionPath: string,
16
+ onProgress?: (deleted: number) => void
17
+ ): Promise<number> {
18
+ let totalDeleted = 0;
19
+ let hasMore = true;
20
+
21
+ while (hasMore) {
22
+ const snapshot = await db
23
+ .collection(collectionPath)
24
+ .orderBy("__name__")
25
+ .limit(BATCH_SIZE)
26
+ .get();
27
+
28
+ if (snapshot.empty) {
29
+ hasMore = false;
30
+ continue;
31
+ }
32
+
33
+ const batch = db.batch();
34
+ snapshot.docs.forEach((doc) => batch.delete(doc.ref));
35
+ await batch.commit();
36
+
37
+ totalDeleted += snapshot.docs.length;
38
+ onProgress?.(totalDeleted);
39
+ }
40
+
41
+ return totalDeleted;
42
+ }
43
+
44
+ /**
45
+ * Delete user subcollection for all users
46
+ */
47
+ export async function deleteUserSubcollection(
48
+ db: admin.firestore.Firestore,
49
+ subcollectionName: string,
50
+ onProgress?: (deleted: number) => void
51
+ ): Promise<number> {
52
+ let totalDeleted = 0;
53
+ const usersSnapshot = await db.collection("users").get();
54
+
55
+ for (const userDoc of usersSnapshot.docs) {
56
+ const subcollectionRef = userDoc.ref.collection(subcollectionName);
57
+ const subcollectionSnapshot = await subcollectionRef.get();
58
+
59
+ if (!subcollectionSnapshot.empty) {
60
+ const batch = db.batch();
61
+ subcollectionSnapshot.docs.forEach((doc) => batch.delete(doc.ref));
62
+ await batch.commit();
63
+ totalDeleted += subcollectionSnapshot.docs.length;
64
+ onProgress?.(totalDeleted);
65
+ }
66
+ }
67
+
68
+ return totalDeleted;
69
+ }
70
+
71
+ /**
72
+ * Delete all Firestore data
73
+ */
74
+ export async function deleteAllData(
75
+ db: admin.firestore.Firestore,
76
+ onProgress?: (collection: string, deleted: number) => void
77
+ ): Promise<number> {
78
+ let totalDeleted = 0;
79
+ const collections = await db.listCollections();
80
+
81
+ for (const collection of collections) {
82
+ const snapshot = await collection.get();
83
+
84
+ // Delete subcollections first for users collection
85
+ if (collection.id === "users") {
86
+ for (const doc of snapshot.docs) {
87
+ const subcollections = await doc.ref.listCollections();
88
+ for (const subcollection of subcollections) {
89
+ const subSnapshot = await subcollection.get();
90
+ if (!subSnapshot.empty) {
91
+ const batch = db.batch();
92
+ subSnapshot.docs.forEach((subDoc) => batch.delete(subDoc.ref));
93
+ await batch.commit();
94
+ totalDeleted += subSnapshot.docs.length;
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ // Delete main collection documents
101
+ if (!snapshot.empty) {
102
+ const batch = db.batch();
103
+ snapshot.docs.forEach((doc) => batch.delete(doc.ref));
104
+ await batch.commit();
105
+ totalDeleted += snapshot.docs.length;
106
+ onProgress?.(collection.id, totalDeleted);
107
+ }
108
+ }
109
+
110
+ return totalDeleted;
111
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Firebase Admin Firestore Queries
3
+ * Query functions for reading Firestore data
4
+ */
5
+
6
+ import * as admin from "firebase-admin";
7
+ import type { CollectionInfo } from "./types";
8
+
9
+ /**
10
+ * List all root-level collections
11
+ */
12
+ export async function listCollections(
13
+ db: admin.firestore.Firestore
14
+ ): Promise<CollectionInfo[]> {
15
+ const collections = await db.listCollections();
16
+ const result: CollectionInfo[] = [];
17
+
18
+ for (const collection of collections) {
19
+ const snapshot = await collection.limit(1000).get();
20
+ const info: CollectionInfo = {
21
+ name: collection.id,
22
+ documentCount: snapshot.docs.length,
23
+ sampleDocumentId: snapshot.docs[0]?.id,
24
+ };
25
+
26
+ if (!snapshot.empty) {
27
+ const subcollections = await snapshot.docs[0].ref.listCollections();
28
+ info.hasSubcollections = subcollections.length > 0;
29
+ }
30
+
31
+ result.push(info);
32
+ }
33
+
34
+ return result.sort((a, b) => b.documentCount - a.documentCount);
35
+ }
36
+
37
+ /**
38
+ * List subcollections for a user document
39
+ */
40
+ export async function listUserSubcollections(
41
+ db: admin.firestore.Firestore,
42
+ userId: string
43
+ ): Promise<CollectionInfo[]> {
44
+ const userRef = db.collection("users").doc(userId);
45
+ const subcollections = await userRef.listCollections();
46
+ const result: CollectionInfo[] = [];
47
+
48
+ for (const subcollection of subcollections) {
49
+ const count = await subcollection.count().get();
50
+ result.push({
51
+ name: subcollection.id,
52
+ documentCount: count.data().count,
53
+ });
54
+ }
55
+
56
+ return result;
57
+ }
58
+
59
+ /**
60
+ * Count documents in collection
61
+ */
62
+ export async function countDocuments(
63
+ db: admin.firestore.Firestore,
64
+ collectionPath: string
65
+ ): Promise<number> {
66
+ const count = await db.collection(collectionPath).count().get();
67
+ return count.data().count;
68
+ }
69
+
70
+ /**
71
+ * Get user document count statistics
72
+ */
73
+ export async function getUserStats(db: admin.firestore.Firestore): Promise<{
74
+ total: number;
75
+ anonymous: number;
76
+ authenticated: number;
77
+ }> {
78
+ const usersSnapshot = await db.collection("users").get();
79
+
80
+ let anonymous = 0;
81
+ let authenticated = 0;
82
+
83
+ usersSnapshot.docs.forEach((doc) => {
84
+ const data = doc.data();
85
+ if (data.isAnonymous) {
86
+ anonymous++;
87
+ } else {
88
+ authenticated++;
89
+ }
90
+ });
91
+
92
+ return {
93
+ total: usersSnapshot.docs.length,
94
+ anonymous,
95
+ authenticated,
96
+ };
97
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Firebase Admin Firestore Seeding
3
+ * Seed operations for Firestore data
4
+ */
5
+
6
+ import * as admin from "firebase-admin";
7
+ import type { BatchResult } from "./types";
8
+
9
+ const BATCH_SIZE = 500;
10
+
11
+ /**
12
+ * Seed documents in batches
13
+ */
14
+ export async function seedBatch(
15
+ db: admin.firestore.Firestore,
16
+ collectionPath: string,
17
+ docs: Array<{ id: string; data: Record<string, unknown> }>
18
+ ): Promise<BatchResult> {
19
+ const result: BatchResult = {
20
+ success: true,
21
+ processed: 0,
22
+ errors: [],
23
+ };
24
+
25
+ for (let i = 0; i < docs.length; i += BATCH_SIZE) {
26
+ const batch = db.batch();
27
+ const slice = docs.slice(i, i + BATCH_SIZE);
28
+
29
+ for (const { id, data } of slice) {
30
+ const ref = db.collection(collectionPath).doc(id);
31
+ const clean = Object.fromEntries(
32
+ Object.entries(data).filter(([, v]) => v !== undefined)
33
+ );
34
+ batch.set(ref, clean);
35
+ }
36
+
37
+ try {
38
+ await batch.commit();
39
+ result.processed += slice.length;
40
+ } catch (error) {
41
+ result.success = false;
42
+ result.errors.push(`Batch failed at index ${i}: ${error}`);
43
+ }
44
+ }
45
+
46
+ return result;
47
+ }
48
+
49
+ /**
50
+ * Seed user subcollection
51
+ */
52
+ export async function seedUserSubcollection(
53
+ db: admin.firestore.Firestore,
54
+ userId: string,
55
+ subcollectionName: string,
56
+ docs: Array<{ id: string; data: Record<string, unknown> }>
57
+ ): Promise<BatchResult> {
58
+ const result: BatchResult = {
59
+ success: true,
60
+ processed: 0,
61
+ errors: [],
62
+ };
63
+
64
+ const batch = db.batch();
65
+
66
+ for (const { id, data } of docs) {
67
+ const ref = db
68
+ .collection("users")
69
+ .doc(userId)
70
+ .collection(subcollectionName)
71
+ .doc(id);
72
+ const clean = Object.fromEntries(
73
+ Object.entries(data).filter(([, v]) => v !== undefined)
74
+ );
75
+ batch.set(ref, clean);
76
+ }
77
+
78
+ try {
79
+ await batch.commit();
80
+ result.processed = docs.length;
81
+ } catch (error) {
82
+ result.success = false;
83
+ result.errors.push(`Failed to seed subcollection: ${error}`);
84
+ }
85
+
86
+ return result;
87
+ }