@umituz/react-native-firebase 1.13.48 → 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.
- package/dist/scripts/cli-handlers.d.ts +27 -0
- package/dist/scripts/cli-handlers.d.ts.map +1 -0
- package/dist/scripts/cli-handlers.js +125 -0
- package/dist/scripts/cli-handlers.js.map +1 -0
- package/dist/scripts/cli-parser.d.ts +25 -0
- package/dist/scripts/cli-parser.d.ts.map +1 -0
- package/dist/scripts/cli-parser.js +101 -0
- package/dist/scripts/cli-parser.js.map +1 -0
- package/dist/scripts/cli.js +20 -155
- package/dist/scripts/cli.js.map +1 -1
- package/dist/scripts/firestore-operations.d.ts +18 -0
- package/dist/scripts/firestore-operations.d.ts.map +1 -0
- package/dist/scripts/firestore-operations.js +88 -0
- package/dist/scripts/firestore-operations.js.map +1 -0
- package/dist/scripts/firestore-queries.d.ts +27 -0
- package/dist/scripts/firestore-queries.d.ts.map +1 -0
- package/dist/scripts/firestore-queries.js +77 -0
- package/dist/scripts/firestore-queries.js.map +1 -0
- package/dist/scripts/firestore-seeding.d.ts +21 -0
- package/dist/scripts/firestore-seeding.d.ts.map +1 -0
- package/dist/scripts/firestore-seeding.js +67 -0
- package/dist/scripts/firestore-seeding.js.map +1 -0
- package/dist/scripts/firestore.d.ts +3 -48
- package/dist/scripts/firestore.d.ts.map +1 -1
- package/dist/scripts/firestore.js +16 -210
- package/dist/scripts/firestore.js.map +1 -1
- package/dist/scripts/user-commands.d.ts +33 -0
- package/dist/scripts/user-commands.d.ts.map +1 -0
- package/dist/scripts/user-commands.js +113 -0
- package/dist/scripts/user-commands.js.map +1 -0
- package/dist/scripts/user-formatters.d.ts +10 -0
- package/dist/scripts/user-formatters.d.ts.map +1 -0
- package/dist/scripts/user-formatters.js +55 -0
- package/dist/scripts/user-formatters.js.map +1 -0
- package/dist/scripts/user-queries.d.ts +42 -0
- package/dist/scripts/user-queries.d.ts.map +1 -0
- package/dist/scripts/user-queries.js +125 -0
- package/dist/scripts/user-queries.js.map +1 -0
- package/dist/scripts/user.d.ts +3 -67
- package/dist/scripts/user.d.ts.map +1 -1
- package/dist/scripts/user.js +15 -272
- package/dist/scripts/user.js.map +1 -1
- package/package.json +1 -1
- package/scripts/cli-handlers.ts +170 -0
- package/scripts/cli-parser.ts +82 -0
- package/scripts/cli.ts +27 -193
- package/scripts/firestore-operations.ts +111 -0
- package/scripts/firestore-queries.ts +97 -0
- package/scripts/firestore-seeding.ts +87 -0
- package/scripts/firestore.ts +20 -275
- package/scripts/user-commands.ts +104 -0
- package/scripts/user-formatters.ts +55 -0
- package/scripts/user-queries.ts +185 -0
- package/scripts/user.ts +19 -326
- package/src/auth/infrastructure/config/FirebaseAuthClient.ts +16 -171
- package/src/auth/infrastructure/services/account-deletion.service.ts +41 -351
- package/src/auth/infrastructure/services/reauthentication.service.ts +47 -207
- package/src/auth/infrastructure/services/reauthentication.types.ts +39 -0
package/dist/scripts/user.js
CHANGED
|
@@ -3,277 +3,20 @@
|
|
|
3
3
|
* Firebase Admin User Utilities
|
|
4
4
|
* Read and manage user data including credits, subscriptions, transactions
|
|
5
5
|
*/
|
|
6
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
-
if (k2 === undefined) k2 = k;
|
|
8
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
-
}
|
|
12
|
-
Object.defineProperty(o, k2, desc);
|
|
13
|
-
}) : (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
o[k2] = m[k];
|
|
16
|
-
}));
|
|
17
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
-
}) : function(o, v) {
|
|
20
|
-
o["default"] = v;
|
|
21
|
-
});
|
|
22
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
-
var ownKeys = function(o) {
|
|
24
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
-
var ar = [];
|
|
26
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
-
return ar;
|
|
28
|
-
};
|
|
29
|
-
return ownKeys(o);
|
|
30
|
-
};
|
|
31
|
-
return function (mod) {
|
|
32
|
-
if (mod && mod.__esModule) return mod;
|
|
33
|
-
var result = {};
|
|
34
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
-
__setModuleDefault(result, mod);
|
|
36
|
-
return result;
|
|
37
|
-
};
|
|
38
|
-
})();
|
|
39
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.getUserData =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
exports.
|
|
44
|
-
exports
|
|
45
|
-
exports.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
userId,
|
|
56
|
-
exists: false,
|
|
57
|
-
profile: null,
|
|
58
|
-
credits: null,
|
|
59
|
-
subscriptions: [],
|
|
60
|
-
transactions: [],
|
|
61
|
-
};
|
|
62
|
-
// Get user profile
|
|
63
|
-
const userDoc = await db.collection("users").doc(userId).get();
|
|
64
|
-
if (userDoc.exists) {
|
|
65
|
-
result.exists = true;
|
|
66
|
-
result.profile = userDoc.data();
|
|
67
|
-
}
|
|
68
|
-
// Get credits from root-level collection
|
|
69
|
-
if (includeCredits) {
|
|
70
|
-
const creditsDoc = await db.collection(creditsCollection).doc(userId).get();
|
|
71
|
-
if (creditsDoc.exists) {
|
|
72
|
-
result.credits = creditsDoc.data();
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Get subscriptions subcollection
|
|
76
|
-
if (includeSubscriptions) {
|
|
77
|
-
const subsSnapshot = await db
|
|
78
|
-
.collection("users")
|
|
79
|
-
.doc(userId)
|
|
80
|
-
.collection("subscriptions")
|
|
81
|
-
.get();
|
|
82
|
-
result.subscriptions = subsSnapshot.docs.map((doc) => ({
|
|
83
|
-
id: doc.id,
|
|
84
|
-
...doc.data(),
|
|
85
|
-
}));
|
|
86
|
-
}
|
|
87
|
-
// Get transactions subcollection
|
|
88
|
-
if (includeTransactions) {
|
|
89
|
-
const txSnapshot = await db
|
|
90
|
-
.collection("users")
|
|
91
|
-
.doc(userId)
|
|
92
|
-
.collection("transactions")
|
|
93
|
-
.orderBy("createdAt", "desc")
|
|
94
|
-
.limit(50)
|
|
95
|
-
.get();
|
|
96
|
-
result.transactions = txSnapshot.docs.map((doc) => ({
|
|
97
|
-
id: doc.id,
|
|
98
|
-
...doc.data(),
|
|
99
|
-
}));
|
|
100
|
-
}
|
|
101
|
-
return result;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Initialize credits for a user
|
|
105
|
-
*/
|
|
106
|
-
async function initializeUserCredits(db, userId, config) {
|
|
107
|
-
const { collectionName = "user_credits", textLimit = 0, imageLimit = 0 } = config;
|
|
108
|
-
const now = admin.firestore.FieldValue.serverTimestamp();
|
|
109
|
-
const credits = {
|
|
110
|
-
text: textLimit,
|
|
111
|
-
image: imageLimit,
|
|
112
|
-
video: 0,
|
|
113
|
-
audio: 0,
|
|
114
|
-
createdAt: now,
|
|
115
|
-
updatedAt: now,
|
|
116
|
-
};
|
|
117
|
-
await db.collection(collectionName).doc(userId).set(credits, { merge: true });
|
|
118
|
-
return {
|
|
119
|
-
text: textLimit,
|
|
120
|
-
image: imageLimit,
|
|
121
|
-
video: 0,
|
|
122
|
-
audio: 0,
|
|
123
|
-
createdAt: new Date(),
|
|
124
|
-
updatedAt: new Date(),
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Add credits to a user
|
|
129
|
-
*/
|
|
130
|
-
async function addUserCredits(db, userId, credits, collectionName = "user_credits") {
|
|
131
|
-
const updates = {
|
|
132
|
-
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
133
|
-
};
|
|
134
|
-
if (credits.text) {
|
|
135
|
-
updates.text = admin.firestore.FieldValue.increment(credits.text);
|
|
136
|
-
}
|
|
137
|
-
if (credits.image) {
|
|
138
|
-
updates.image = admin.firestore.FieldValue.increment(credits.image);
|
|
139
|
-
}
|
|
140
|
-
if (credits.video) {
|
|
141
|
-
updates.video = admin.firestore.FieldValue.increment(credits.video);
|
|
142
|
-
}
|
|
143
|
-
if (credits.audio) {
|
|
144
|
-
updates.audio = admin.firestore.FieldValue.increment(credits.audio);
|
|
145
|
-
}
|
|
146
|
-
await db.collection(collectionName).doc(userId).update(updates);
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Set credits for a user (overwrite)
|
|
150
|
-
*/
|
|
151
|
-
async function setUserCredits(db, userId, credits, collectionName = "user_credits") {
|
|
152
|
-
const updates = {
|
|
153
|
-
updatedAt: admin.firestore.FieldValue.serverTimestamp(),
|
|
154
|
-
};
|
|
155
|
-
if (credits.text !== undefined)
|
|
156
|
-
updates.text = credits.text;
|
|
157
|
-
if (credits.image !== undefined)
|
|
158
|
-
updates.image = credits.image;
|
|
159
|
-
if (credits.video !== undefined)
|
|
160
|
-
updates.video = credits.video;
|
|
161
|
-
if (credits.audio !== undefined)
|
|
162
|
-
updates.audio = credits.audio;
|
|
163
|
-
await db.collection(collectionName).doc(userId).set(updates, { merge: true });
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* List all users with their credit balances
|
|
167
|
-
*/
|
|
168
|
-
async function listUsersWithCredits(db, options) {
|
|
169
|
-
const { creditsCollection = "user_credits", limit = 100, onlyWithCredits = false } = options || {};
|
|
170
|
-
const usersSnapshot = await db.collection("users").limit(limit).get();
|
|
171
|
-
const result = [];
|
|
172
|
-
for (const userDoc of usersSnapshot.docs) {
|
|
173
|
-
const userData = userDoc.data();
|
|
174
|
-
const creditsDoc = await db.collection(creditsCollection).doc(userDoc.id).get();
|
|
175
|
-
const credits = creditsDoc.exists ? creditsDoc.data() : null;
|
|
176
|
-
if (onlyWithCredits && !credits)
|
|
177
|
-
continue;
|
|
178
|
-
result.push({
|
|
179
|
-
userId: userDoc.id,
|
|
180
|
-
displayName: userData.displayName,
|
|
181
|
-
email: userData.email,
|
|
182
|
-
isAnonymous: userData.isAnonymous || false,
|
|
183
|
-
credits,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
return result;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Delete user credits document
|
|
190
|
-
*/
|
|
191
|
-
async function deleteUserCredits(db, userId, collectionName = "user_credits") {
|
|
192
|
-
await db.collection(collectionName).doc(userId).delete();
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Get credits summary across all users
|
|
196
|
-
*/
|
|
197
|
-
async function getCreditsSummary(db, collectionName = "user_credits") {
|
|
198
|
-
const snapshot = await db.collection(collectionName).get();
|
|
199
|
-
let totalText = 0;
|
|
200
|
-
let totalImage = 0;
|
|
201
|
-
let totalVideo = 0;
|
|
202
|
-
let totalAudio = 0;
|
|
203
|
-
let usersWithCredits = 0;
|
|
204
|
-
let usersWithZeroCredits = 0;
|
|
205
|
-
snapshot.docs.forEach((doc) => {
|
|
206
|
-
const data = doc.data();
|
|
207
|
-
const text = data.text || 0;
|
|
208
|
-
const image = data.image || 0;
|
|
209
|
-
const video = data.video || 0;
|
|
210
|
-
const audio = data.audio || 0;
|
|
211
|
-
totalText += text;
|
|
212
|
-
totalImage += image;
|
|
213
|
-
totalVideo += video;
|
|
214
|
-
totalAudio += audio;
|
|
215
|
-
if (text > 0 || image > 0 || video > 0 || audio > 0) {
|
|
216
|
-
usersWithCredits++;
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
usersWithZeroCredits++;
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
return {
|
|
223
|
-
totalUsers: snapshot.docs.length,
|
|
224
|
-
totalText,
|
|
225
|
-
totalImage,
|
|
226
|
-
totalVideo,
|
|
227
|
-
totalAudio,
|
|
228
|
-
usersWithCredits,
|
|
229
|
-
usersWithZeroCredits,
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Print user data in formatted way
|
|
234
|
-
*/
|
|
235
|
-
function printUserData(data) {
|
|
236
|
-
console.log("\n" + "═".repeat(60));
|
|
237
|
-
console.log(`👤 USER: ${data.userId}`);
|
|
238
|
-
console.log("═".repeat(60));
|
|
239
|
-
console.log("\n📋 PROFILE:");
|
|
240
|
-
if (data.profile) {
|
|
241
|
-
console.log(JSON.stringify(data.profile, null, 2));
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
console.log(" ❌ Not found");
|
|
245
|
-
}
|
|
246
|
-
console.log("\n💰 CREDITS:");
|
|
247
|
-
if (data.credits) {
|
|
248
|
-
console.log(` Text: ${data.credits.text || 0}`);
|
|
249
|
-
console.log(` Image: ${data.credits.image || 0}`);
|
|
250
|
-
console.log(` Video: ${data.credits.video || 0}`);
|
|
251
|
-
console.log(` Audio: ${data.credits.audio || 0}`);
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
console.log(" ❌ Not found");
|
|
255
|
-
}
|
|
256
|
-
console.log("\n🔔 SUBSCRIPTIONS:");
|
|
257
|
-
if (data.subscriptions.length > 0) {
|
|
258
|
-
data.subscriptions.forEach((sub) => {
|
|
259
|
-
console.log(` - ${sub.id}: ${JSON.stringify(sub)}`);
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
console.log(" ❌ None");
|
|
264
|
-
}
|
|
265
|
-
console.log("\n🧾 TRANSACTIONS:");
|
|
266
|
-
if (data.transactions.length > 0) {
|
|
267
|
-
data.transactions.slice(0, 5).forEach((tx) => {
|
|
268
|
-
console.log(` - ${tx.id}: ${JSON.stringify(tx)}`);
|
|
269
|
-
});
|
|
270
|
-
if (data.transactions.length > 5) {
|
|
271
|
-
console.log(` ... and ${data.transactions.length - 5} more`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
else {
|
|
275
|
-
console.log(" ❌ None");
|
|
276
|
-
}
|
|
277
|
-
console.log("\n" + "═".repeat(60) + "\n");
|
|
278
|
-
}
|
|
7
|
+
exports.printUserData = exports.deleteUserCredits = exports.setUserCredits = exports.addUserCredits = exports.initializeUserCredits = exports.getCreditsSummary = exports.listUsersWithCredits = exports.getUserData = void 0;
|
|
8
|
+
// Query functions
|
|
9
|
+
var user_queries_1 = require("./user-queries");
|
|
10
|
+
Object.defineProperty(exports, "getUserData", { enumerable: true, get: function () { return user_queries_1.getUserData; } });
|
|
11
|
+
Object.defineProperty(exports, "listUsersWithCredits", { enumerable: true, get: function () { return user_queries_1.listUsersWithCredits; } });
|
|
12
|
+
Object.defineProperty(exports, "getCreditsSummary", { enumerable: true, get: function () { return user_queries_1.getCreditsSummary; } });
|
|
13
|
+
// Command functions
|
|
14
|
+
var user_commands_1 = require("./user-commands");
|
|
15
|
+
Object.defineProperty(exports, "initializeUserCredits", { enumerable: true, get: function () { return user_commands_1.initializeUserCredits; } });
|
|
16
|
+
Object.defineProperty(exports, "addUserCredits", { enumerable: true, get: function () { return user_commands_1.addUserCredits; } });
|
|
17
|
+
Object.defineProperty(exports, "setUserCredits", { enumerable: true, get: function () { return user_commands_1.setUserCredits; } });
|
|
18
|
+
Object.defineProperty(exports, "deleteUserCredits", { enumerable: true, get: function () { return user_commands_1.deleteUserCredits; } });
|
|
19
|
+
// Formatter functions
|
|
20
|
+
var user_formatters_1 = require("./user-formatters");
|
|
21
|
+
Object.defineProperty(exports, "printUserData", { enumerable: true, get: function () { return user_formatters_1.printUserData; } });
|
|
279
22
|
//# sourceMappingURL=user.js.map
|
package/dist/scripts/user.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../scripts/user.ts"],"names":[],"mappings":";AAAA;;;GAGG
|
|
1
|
+
{"version":3,"file":"user.js","sourceRoot":"","sources":["../../scripts/user.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,kBAAkB;AAClB,+CAIwB;AAHtB,2GAAA,WAAW,OAAA;AACX,oHAAA,oBAAoB,OAAA;AACpB,iHAAA,iBAAiB,OAAA;AAGnB,oBAAoB;AACpB,iDAKyB;AAJvB,sHAAA,qBAAqB,OAAA;AACrB,+GAAA,cAAc,OAAA;AACd,+GAAA,cAAc,OAAA;AACd,kHAAA,iBAAiB,OAAA;AAGnB,sBAAsB;AACtB,qDAE2B;AADzB,gHAAA,aAAa,OAAA"}
|
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.50",
|
|
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",
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Admin CLI Command Handlers
|
|
3
|
+
* Individual command implementations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as admin from "firebase-admin";
|
|
7
|
+
import type { CLIOptions } from "./cli-parser";
|
|
8
|
+
import {
|
|
9
|
+
getUserData,
|
|
10
|
+
initializeUserCredits,
|
|
11
|
+
setUserCredits,
|
|
12
|
+
listUsersWithCredits,
|
|
13
|
+
getCreditsSummary,
|
|
14
|
+
printUserData,
|
|
15
|
+
} from "./user";
|
|
16
|
+
import { printHeader, printSeparator } from "./utils";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Handle read-user command
|
|
20
|
+
*/
|
|
21
|
+
export async function handleReadUser(
|
|
22
|
+
db: admin.firestore.Firestore,
|
|
23
|
+
args: string[],
|
|
24
|
+
options: CLIOptions
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
const userId = args[0];
|
|
27
|
+
if (!userId) {
|
|
28
|
+
console.error("❌ Error: userId is required");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
printHeader(`📖 READ USER: ${userId}`);
|
|
33
|
+
const userData = await getUserData(db, userId, {
|
|
34
|
+
creditsCollection: options.creditsCollection,
|
|
35
|
+
});
|
|
36
|
+
printUserData(userData);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Handle init-credits command
|
|
41
|
+
*/
|
|
42
|
+
export async function handleInitCredits(
|
|
43
|
+
db: admin.firestore.Firestore,
|
|
44
|
+
args: string[],
|
|
45
|
+
options: CLIOptions
|
|
46
|
+
): Promise<void> {
|
|
47
|
+
const userId = args[0];
|
|
48
|
+
if (!userId) {
|
|
49
|
+
console.error("❌ Error: userId is required");
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
printHeader(`💰 INIT CREDITS: ${userId}`);
|
|
54
|
+
console.log(`Collection: ${options.creditsCollection}`);
|
|
55
|
+
console.log(`Limits: Text=${options.textLimit}, Image=${options.imageLimit}\n`);
|
|
56
|
+
|
|
57
|
+
const existing = await getUserData(db, userId, {
|
|
58
|
+
creditsCollection: options.creditsCollection,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (existing.credits) {
|
|
62
|
+
console.log("⚠️ Credits already exist:");
|
|
63
|
+
console.log(` Text: ${existing.credits.text}`);
|
|
64
|
+
console.log(` Image: ${existing.credits.image}`);
|
|
65
|
+
console.log("\n Use 'set-credits' to overwrite.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const credits = await initializeUserCredits(db, userId, {
|
|
70
|
+
collectionName: options.creditsCollection,
|
|
71
|
+
textLimit: options.textLimit,
|
|
72
|
+
imageLimit: options.imageLimit,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
console.log("✅ Credits initialized:");
|
|
76
|
+
console.log(` Text: ${credits.text}`);
|
|
77
|
+
console.log(` Image: ${credits.image}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Handle set-credits command
|
|
82
|
+
*/
|
|
83
|
+
export async function handleSetCredits(
|
|
84
|
+
db: admin.firestore.Firestore,
|
|
85
|
+
args: string[],
|
|
86
|
+
options: CLIOptions
|
|
87
|
+
): Promise<void> {
|
|
88
|
+
const userId = args[0];
|
|
89
|
+
const text = parseInt(args[1]);
|
|
90
|
+
const image = parseInt(args[2]);
|
|
91
|
+
|
|
92
|
+
if (!userId || isNaN(text) || isNaN(image)) {
|
|
93
|
+
console.error("❌ Error: Usage: set-credits <userId> <text> <image>");
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
printHeader(`💰 SET CREDITS: ${userId}`);
|
|
98
|
+
console.log(`Setting: Text=${text}, Image=${image}\n`);
|
|
99
|
+
|
|
100
|
+
await setUserCredits(db, userId, { text, image }, options.creditsCollection);
|
|
101
|
+
|
|
102
|
+
console.log("✅ Credits set successfully!");
|
|
103
|
+
|
|
104
|
+
const updated = await getUserData(db, userId, {
|
|
105
|
+
creditsCollection: options.creditsCollection,
|
|
106
|
+
});
|
|
107
|
+
printUserData(updated);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Handle list-users command
|
|
112
|
+
*/
|
|
113
|
+
export async function handleListUsers(
|
|
114
|
+
db: admin.firestore.Firestore,
|
|
115
|
+
args: string[],
|
|
116
|
+
options: CLIOptions
|
|
117
|
+
): Promise<void> {
|
|
118
|
+
const limit = parseInt(args[0]) || 100;
|
|
119
|
+
|
|
120
|
+
printHeader("👥 USERS WITH CREDITS");
|
|
121
|
+
const users = await listUsersWithCredits(db, {
|
|
122
|
+
creditsCollection: options.creditsCollection,
|
|
123
|
+
limit,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
console.log(`Found ${users.length} users:\n`);
|
|
127
|
+
printSeparator("-", 80);
|
|
128
|
+
console.log(
|
|
129
|
+
"ID".padEnd(30) +
|
|
130
|
+
"Name".padEnd(20) +
|
|
131
|
+
"Text".padEnd(10) +
|
|
132
|
+
"Image".padEnd(10) +
|
|
133
|
+
"Anon"
|
|
134
|
+
);
|
|
135
|
+
printSeparator("-", 80);
|
|
136
|
+
|
|
137
|
+
users.forEach((u) => {
|
|
138
|
+
const text = u.credits?.text ?? "-";
|
|
139
|
+
const image = u.credits?.image ?? "-";
|
|
140
|
+
console.log(
|
|
141
|
+
u.userId.substring(0, 28).padEnd(30) +
|
|
142
|
+
(u.displayName || "-").substring(0, 18).padEnd(20) +
|
|
143
|
+
String(text).padEnd(10) +
|
|
144
|
+
String(image).padEnd(10) +
|
|
145
|
+
(u.isAnonymous ? "Yes" : "No")
|
|
146
|
+
);
|
|
147
|
+
});
|
|
148
|
+
printSeparator("-", 80);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Handle credits-summary command
|
|
153
|
+
*/
|
|
154
|
+
export async function handleCreditsSummary(
|
|
155
|
+
db: admin.firestore.Firestore,
|
|
156
|
+
options: CLIOptions
|
|
157
|
+
): Promise<void> {
|
|
158
|
+
printHeader("📊 CREDITS SUMMARY");
|
|
159
|
+
const summary = await getCreditsSummary(db, options.creditsCollection);
|
|
160
|
+
|
|
161
|
+
console.log(`Total Users: ${summary.totalUsers}`);
|
|
162
|
+
console.log(`With Credits: ${summary.usersWithCredits}`);
|
|
163
|
+
console.log(`Zero Credits: ${summary.usersWithZeroCredits}`);
|
|
164
|
+
console.log();
|
|
165
|
+
console.log("Total Credits Across All Users:");
|
|
166
|
+
console.log(` Text: ${summary.totalText}`);
|
|
167
|
+
console.log(` Image: ${summary.totalImage}`);
|
|
168
|
+
console.log(` Video: ${summary.totalVideo}`);
|
|
169
|
+
console.log(` Audio: ${summary.totalAudio}`);
|
|
170
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firebase Admin CLI Parser
|
|
3
|
+
* Command line argument parsing utilities
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
|
|
9
|
+
export interface CLIOptions {
|
|
10
|
+
serviceAccountPath: string;
|
|
11
|
+
projectId?: string;
|
|
12
|
+
creditsCollection: string;
|
|
13
|
+
textLimit: number;
|
|
14
|
+
imageLimit: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ParsedArgs {
|
|
18
|
+
command: string;
|
|
19
|
+
args: string[];
|
|
20
|
+
options: CLIOptions;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parse command line arguments
|
|
25
|
+
*/
|
|
26
|
+
export function parseArgs(): ParsedArgs {
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const command = args[0] || "help";
|
|
29
|
+
const commandArgs: string[] = [];
|
|
30
|
+
const options: CLIOptions = {
|
|
31
|
+
serviceAccountPath: "./firebase-service-account.json",
|
|
32
|
+
creditsCollection: "user_credits",
|
|
33
|
+
textLimit: 100,
|
|
34
|
+
imageLimit: 100,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let i = 1;
|
|
38
|
+
while (i < args.length) {
|
|
39
|
+
const arg = args[i];
|
|
40
|
+
if (arg.startsWith("--")) {
|
|
41
|
+
const key = arg.slice(2);
|
|
42
|
+
const value = args[++i];
|
|
43
|
+
switch (key) {
|
|
44
|
+
case "service-account":
|
|
45
|
+
options.serviceAccountPath = value;
|
|
46
|
+
break;
|
|
47
|
+
case "project-id":
|
|
48
|
+
options.projectId = value;
|
|
49
|
+
break;
|
|
50
|
+
case "credits-collection":
|
|
51
|
+
options.creditsCollection = value;
|
|
52
|
+
break;
|
|
53
|
+
case "text-limit":
|
|
54
|
+
options.textLimit = parseInt(value) || 100;
|
|
55
|
+
break;
|
|
56
|
+
case "image-limit":
|
|
57
|
+
options.imageLimit = parseInt(value) || 100;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
commandArgs.push(arg);
|
|
62
|
+
}
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return { command, args: commandArgs, options };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get project ID from options or service account
|
|
71
|
+
*/
|
|
72
|
+
export function getProjectId(options: CLIOptions): string {
|
|
73
|
+
if (options.projectId) return options.projectId;
|
|
74
|
+
|
|
75
|
+
const saPath = path.resolve(process.cwd(), options.serviceAccountPath);
|
|
76
|
+
if (fs.existsSync(saPath)) {
|
|
77
|
+
const sa = JSON.parse(fs.readFileSync(saPath, "utf8"));
|
|
78
|
+
return sa.project_id;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
throw new Error("Project ID not found. Use --project-id or ensure service account file exists.");
|
|
82
|
+
}
|