fire-pilot-rn 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/GoogleService-Info.plist +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +391 -0
  4. package/build/commands/enable.d.ts +2 -0
  5. package/build/commands/enable.d.ts.map +1 -0
  6. package/build/commands/enable.js +73 -0
  7. package/build/commands/enable.js.map +1 -0
  8. package/build/commands/login.d.ts +2 -0
  9. package/build/commands/login.d.ts.map +1 -0
  10. package/build/commands/login.js +117 -0
  11. package/build/commands/login.js.map +1 -0
  12. package/build/commands/setup.d.ts +2 -0
  13. package/build/commands/setup.d.ts.map +1 -0
  14. package/build/commands/setup.js +297 -0
  15. package/build/commands/setup.js.map +1 -0
  16. package/build/commands/sha.d.ts +7 -0
  17. package/build/commands/sha.d.ts.map +1 -0
  18. package/build/commands/sha.js +165 -0
  19. package/build/commands/sha.js.map +1 -0
  20. package/build/index.d.ts +3 -0
  21. package/build/index.d.ts.map +1 -0
  22. package/build/index.js +59 -0
  23. package/build/index.js.map +1 -0
  24. package/build/utils/checker.d.ts +2 -0
  25. package/build/utils/checker.d.ts.map +1 -0
  26. package/build/utils/checker.js +100 -0
  27. package/build/utils/checker.js.map +1 -0
  28. package/build/utils/logger.d.ts +11 -0
  29. package/build/utils/logger.d.ts.map +1 -0
  30. package/build/utils/logger.js +18 -0
  31. package/build/utils/logger.js.map +1 -0
  32. package/build/utils/runner.d.ts +7 -0
  33. package/build/utils/runner.d.ts.map +1 -0
  34. package/build/utils/runner.js +125 -0
  35. package/build/utils/runner.js.map +1 -0
  36. package/dist/commands/enable.d.ts +2 -0
  37. package/dist/commands/enable.d.ts.map +1 -0
  38. package/dist/commands/enable.js +65 -0
  39. package/dist/commands/enable.js.map +1 -0
  40. package/dist/commands/login.d.ts +2 -0
  41. package/dist/commands/login.d.ts.map +1 -0
  42. package/dist/commands/login.js +86 -0
  43. package/dist/commands/login.js.map +1 -0
  44. package/dist/commands/setup.d.ts +2 -0
  45. package/dist/commands/setup.d.ts.map +1 -0
  46. package/dist/commands/setup.js +133 -0
  47. package/dist/commands/setup.js.map +1 -0
  48. package/dist/commands/sha.d.ts +2 -0
  49. package/dist/commands/sha.d.ts.map +1 -0
  50. package/dist/commands/sha.js +118 -0
  51. package/dist/commands/sha.js.map +1 -0
  52. package/dist/index.d.ts +3 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +59 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/utils/checker.d.ts +2 -0
  57. package/dist/utils/checker.d.ts.map +1 -0
  58. package/dist/utils/checker.js +100 -0
  59. package/dist/utils/checker.js.map +1 -0
  60. package/dist/utils/logger.d.ts +11 -0
  61. package/dist/utils/logger.d.ts.map +1 -0
  62. package/dist/utils/logger.js +18 -0
  63. package/dist/utils/logger.js.map +1 -0
  64. package/dist/utils/runner.d.ts +4 -0
  65. package/dist/utils/runner.d.ts.map +1 -0
  66. package/dist/utils/runner.js +36 -0
  67. package/dist/utils/runner.js.map +1 -0
  68. package/google-services.json +48 -0
  69. package/package.json +51 -0
  70. package/src/commands/enable.ts +80 -0
  71. package/src/commands/login.ts +119 -0
  72. package/src/commands/setup.ts +313 -0
  73. package/src/commands/sha.ts +177 -0
  74. package/src/index.ts +65 -0
  75. package/src/utils/checker.ts +70 -0
  76. package/src/utils/logger.ts +13 -0
  77. package/src/utils/runner.ts +98 -0
  78. package/tsconfig.json +20 -0
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.shaCommand = shaCommand;
40
+ const os = __importStar(require("os"));
41
+ const path = __importStar(require("path"));
42
+ const inquirer_1 = __importDefault(require("inquirer"));
43
+ const runner_1 = require("../utils/runner");
44
+ const logger_1 = require("../utils/logger");
45
+ async function shaCommand() {
46
+ logger_1.logger.title('SHA Key Registration');
47
+ // ── Check keytool exists ─────────────────────────────────────
48
+ if (!(0, runner_1.commandExists)('keytool')) {
49
+ logger_1.logger.error('Java keytool not found!');
50
+ logger_1.logger.info('Install Java from: https://adoptium.net');
51
+ process.exit(1);
52
+ }
53
+ // ── Find the Android debug keystore ─────────────────────────
54
+ const keystorePath = path.join(os.homedir(), '.android', 'debug.keystore');
55
+ logger_1.logger.info(`Looking for keystore at: ${keystorePath}`);
56
+ // ── Extract SHA keys ─────────────────────────────────────────
57
+ logger_1.logger.step('Extracting SHA-1 and SHA-256 from debug keystore...');
58
+ const output = (0, runner_1.runSilent)('keytool', [
59
+ '-list', '-v',
60
+ '-keystore', keystorePath,
61
+ '-alias', 'androiddebugkey',
62
+ '-storepass', 'android',
63
+ '-keypass', 'android',
64
+ ]);
65
+ if (!output) {
66
+ logger_1.logger.error('Could not read keystore. Make sure you have run your React Native Android app at least once.');
67
+ process.exit(1);
68
+ }
69
+ // ── Parse SHA-1 and SHA-256 ──────────────────────────────────
70
+ const sha1Match = output.match(/SHA1:\s+([A-F0-9:]+)/i);
71
+ const sha256Match = output.match(/SHA256:\s+([A-F0-9:]+)/i);
72
+ if (!sha1Match || !sha256Match) {
73
+ logger_1.logger.error('SHA keys not found in keystore output.');
74
+ process.exit(1);
75
+ }
76
+ const sha1 = sha1Match[1].trim();
77
+ const sha256 = sha256Match[1].trim();
78
+ logger_1.logger.success(`SHA-1: ${sha1}`);
79
+ logger_1.logger.success(`SHA-256: ${sha256}`);
80
+ // ── Ask for Firebase project ID ──────────────────────────────
81
+ logger_1.logger.step('Fetching your Firebase projects...');
82
+ (0, runner_1.runLive)('firebase', ['projects:list']);
83
+ const { projectId } = await inquirer_1.default.prompt([
84
+ {
85
+ type: 'input',
86
+ name: 'projectId',
87
+ message: 'Enter your Firebase Project ID (from the list above):',
88
+ validate: (val) => val.trim().length > 0 ? true : 'Project ID cannot be empty',
89
+ },
90
+ ]);
91
+ // ── Ask for Android App ID ───────────────────────────────────
92
+ const { appId } = await inquirer_1.default.prompt([
93
+ {
94
+ type: 'input',
95
+ name: 'appId',
96
+ message: 'Enter your Android App ID (e.g. com.yourapp):',
97
+ validate: (val) => val.trim().length > 0 ? true : 'App ID cannot be empty',
98
+ },
99
+ ]);
100
+ // ── Register SHA keys ────────────────────────────────────────
101
+ logger_1.logger.step('Registering SHA-1 key with Firebase...');
102
+ (0, runner_1.runLive)('firebase', [
103
+ 'apps:android:sha:create',
104
+ '--project', projectId,
105
+ appId,
106
+ sha1,
107
+ ]);
108
+ logger_1.logger.step('Registering SHA-256 key with Firebase...');
109
+ (0, runner_1.runLive)('firebase', [
110
+ 'apps:android:sha:create',
111
+ '--project', projectId,
112
+ appId,
113
+ sha256,
114
+ ]);
115
+ logger_1.logger.success('Both SHA keys registered successfully!');
116
+ logger_1.logger.info('Go to Firebase Console → Project Settings → Your Android App to verify.');
117
+ }
118
+ //# sourceMappingURL=sha.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sha.js","sourceRoot":"","sources":["../../src/commands/sha.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const setup_1 = require("./commands/setup");
6
+ const login_1 = require("./commands/login");
7
+ const sha_1 = require("./commands/sha");
8
+ const enable_1 = require("./commands/enable");
9
+ const program = new commander_1.Command();
10
+ program
11
+ .name('fire-pilot-rn')
12
+ .description('🔥 Elite Firebase setup orchestrator for React Native')
13
+ .version('1.0.0');
14
+ // ── Parent command: firebase ─────────────────────────────────
15
+ const firebase = program.command('firebase');
16
+ // firebase setup --full
17
+ firebase
18
+ .command('setup')
19
+ .description('The complete Pilot experience: Tools → Login → Project → Deps → SHA')
20
+ .option('--full', 'Run the complete setup including SHA key registration')
21
+ .action((options) => {
22
+ (0, setup_1.setupCommand)(options.full ?? false).catch((err) => {
23
+ console.error('Error:', err.message);
24
+ process.exit(1);
25
+ });
26
+ });
27
+ // firebase login
28
+ firebase
29
+ .command('login')
30
+ .description('Manage and switch between multiple Google accounts')
31
+ .action(() => {
32
+ (0, login_1.loginCommand)().catch((err) => {
33
+ console.error('Error:', err.message);
34
+ process.exit(1);
35
+ });
36
+ });
37
+ // firebase sha add
38
+ firebase
39
+ .command('sha')
40
+ .command('add')
41
+ .description('Automatically extract and add SHA keys to your Firebase project')
42
+ .action(() => {
43
+ (0, sha_1.shaCommand)().catch((err) => {
44
+ console.error('Error:', err.message);
45
+ process.exit(1);
46
+ });
47
+ });
48
+ // firebase enable <feature>
49
+ firebase
50
+ .command('enable [feature]')
51
+ .description('Quickly enable Firebase features (auth, firestore, storage, etc.)')
52
+ .action((feature) => {
53
+ (0, enable_1.enableCommand)(feature).catch((err) => {
54
+ console.error('Error:', err.message);
55
+ process.exit(1);
56
+ });
57
+ });
58
+ program.parse(process.argv);
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,4CAAiD;AACjD,4CAAiD;AACjD,wCAA+C;AAC/C,8CAAkD;AAElD,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,uDAAuD,CAAC;KACpE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,gEAAgE;AAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE7C,wBAAwB;AACxB,QAAQ;KACL,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qEAAqE,CAAC;KAClF,MAAM,CAAC,QAAQ,EAAE,uDAAuD,CAAC;KACzE,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE;IAClB,IAAA,oBAAY,EAAC,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAChD,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,iBAAiB;AACjB,QAAQ;KACL,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,oDAAoD,CAAC;KACjE,MAAM,CAAC,GAAG,EAAE;IACX,IAAA,oBAAY,GAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,mBAAmB;AACnB,QAAQ;KACL,OAAO,CAAC,KAAK,CAAC;KACd,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,iEAAiE,CAAC;KAC9E,MAAM,CAAC,GAAG,EAAE;IACX,IAAA,gBAAU,GAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,4BAA4B;AAC5B,QAAQ;KACL,OAAO,CAAC,kBAAkB,CAAC;KAC3B,WAAW,CAAC,mEAAmE,CAAC;KAChF,MAAM,CAAC,CAAC,OAAgB,EAAE,EAAE;IAC3B,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function checkAllTools(): Promise<void>;
2
+ //# sourceMappingURL=checker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../../src/utils/checker.ts"],"names":[],"mappings":"AA8DA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAOnD"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.checkAllTools = checkAllTools;
37
+ const os = __importStar(require("os"));
38
+ const runner_1 = require("./runner");
39
+ const logger_1 = require("./logger");
40
+ // ─── Check Node.js ───────────────────────────────────────────
41
+ async function ensureNode() {
42
+ if ((0, runner_1.commandExists)('node')) {
43
+ const version = (0, runner_1.runSilent)('node', ['--version']);
44
+ logger_1.logger.success(`Node.js found: ${version}`);
45
+ return;
46
+ }
47
+ logger_1.logger.warn('Node.js not found! Attempting to install...');
48
+ const platform = os.platform();
49
+ if (platform === 'win32') {
50
+ (0, runner_1.runLive)('winget', ['install', 'OpenJS.NodeJS.LTS']);
51
+ }
52
+ else if (platform === 'darwin') {
53
+ (0, runner_1.runLive)('brew', ['install', 'node']);
54
+ }
55
+ else {
56
+ logger_1.logger.error('Please install Node.js manually: https://nodejs.org');
57
+ process.exit(1);
58
+ }
59
+ logger_1.logger.success('Node.js installed successfully!');
60
+ }
61
+ // ─── Check NPM ───────────────────────────────────────────────
62
+ async function ensureNpm() {
63
+ if ((0, runner_1.commandExists)('npm')) {
64
+ const version = (0, runner_1.runSilent)('npm', ['--version']);
65
+ logger_1.logger.success(`NPM found: v${version}`);
66
+ return;
67
+ }
68
+ logger_1.logger.error('NPM not found. Please reinstall Node.js from https://nodejs.org');
69
+ process.exit(1);
70
+ }
71
+ // ─── Check Firebase CLI ──────────────────────────────────────
72
+ async function ensureFirebaseCLI() {
73
+ if ((0, runner_1.commandExists)('firebase')) {
74
+ const version = (0, runner_1.runSilent)('firebase', ['--version']);
75
+ logger_1.logger.success(`Firebase CLI found: v${version}`);
76
+ return;
77
+ }
78
+ logger_1.logger.warn('Firebase CLI not found! Installing...');
79
+ (0, runner_1.runLive)('npm', ['install', '-g', 'firebase-tools']);
80
+ logger_1.logger.success('Firebase CLI installed!');
81
+ }
82
+ // ─── Check Java (needed for SHA key extraction) ──────────────
83
+ async function ensureJava() {
84
+ if ((0, runner_1.commandExists)('keytool')) {
85
+ logger_1.logger.success('Java keytool found ✓');
86
+ return;
87
+ }
88
+ logger_1.logger.warn('Java keytool not found. SHA extraction may not work.');
89
+ logger_1.logger.info('Install Java from: https://adoptium.net');
90
+ }
91
+ // ─── Main checker ────────────────────────────────────────────
92
+ async function checkAllTools() {
93
+ logger_1.logger.title('Checking Required Tools');
94
+ await ensureNode();
95
+ await ensureNpm();
96
+ await ensureFirebaseCLI();
97
+ await ensureJava();
98
+ logger_1.logger.success('All required tools are ready!\n');
99
+ }
100
+ //# sourceMappingURL=checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/utils/checker.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DA,sCAOC;AArED,uCAAyB;AACzB,qCAA6D;AAC7D,qCAAkC;AAElC,gEAAgE;AAChE,KAAK,UAAU,UAAU;IACvB,IAAI,IAAA,sBAAa,EAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAA,kBAAS,EAAC,MAAM,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QACjD,eAAM,CAAC,OAAO,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,eAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAE/B,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,IAAA,gBAAO,EAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC,CAAC;IACtD,CAAC;SAAM,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,IAAA,gBAAO,EAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,eAAM,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,eAAM,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;AACpD,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,SAAS;IACtB,IAAI,IAAA,sBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAA,kBAAS,EAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QAChD,eAAM,CAAC,OAAO,CAAC,eAAe,OAAO,EAAE,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IACD,eAAM,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;IAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,iBAAiB;IAC9B,IAAI,IAAA,sBAAa,EAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAA,kBAAS,EAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;QACrD,eAAM,CAAC,OAAO,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,eAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACrD,IAAA,gBAAO,EAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACpD,eAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;AAC5C,CAAC;AAED,gEAAgE;AAChE,KAAK,UAAU,UAAU;IACvB,IAAI,IAAA,sBAAa,EAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,eAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,eAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;IACpE,eAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;AACzD,CAAC;AAED,gEAAgE;AACzD,KAAK,UAAU,aAAa;IACjC,eAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IACxC,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,SAAS,EAAE,CAAC;IAClB,MAAM,iBAAiB,EAAE,CAAC;IAC1B,MAAM,UAAU,EAAE,CAAC;IACnB,eAAM,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ export declare const logger: {
3
+ info: (msg: string) => void;
4
+ success: (msg: string) => void;
5
+ error: (msg: string) => void;
6
+ warn: (msg: string) => void;
7
+ title: (msg: string) => void;
8
+ step: (msg: string) => void;
9
+ running: (msg: string) => void;
10
+ };
11
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";AAGA,eAAO,MAAM,MAAM;gBACL,MAAM;mBACH,MAAM;iBACR,MAAM;gBACP,MAAM;iBACL,MAAM;gBAEP,MAAM;mBACH,MAAM;CACtB,CAAC"}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logger = void 0;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ exports.logger = {
10
+ info: (msg) => console.log(chalk_1.default.cyan('ℹ️ ' + msg)),
11
+ success: (msg) => console.log(chalk_1.default.green('✅ ' + msg)),
12
+ error: (msg) => console.log(chalk_1.default.red('❌ ' + msg)),
13
+ warn: (msg) => console.log(chalk_1.default.yellow('⚠️ ' + msg)),
14
+ title: (msg) => console.log(chalk_1.default.bold.magenta('\n🚀 ' + msg + '\n')),
15
+ step: (msg) => console.log(chalk_1.default.bold.white('\n👉 ' + msg)),
16
+ running: (msg) => console.log(chalk_1.default.gray(' Running: ' + msg)),
17
+ };
18
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":";;;;;;;AACA,kDAA0B;AAEb,QAAA,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC5D,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IAC9D,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IAC1D,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IAC9D,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CACrB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC;IACnE,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC,CAAC;CACxE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function runLive(command: string, args?: string[]): void;
2
+ export declare function runSilent(command: string, args?: string[]): string;
3
+ export declare function commandExists(command: string): boolean;
4
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/utils/runner.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,IAAI,CAMlE;AAGD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,MAAM,CAOtE;AAGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOtD"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runLive = runLive;
4
+ exports.runSilent = runSilent;
5
+ exports.commandExists = commandExists;
6
+ const child_process_1 = require("child_process");
7
+ const logger_1 = require("./logger");
8
+ // Run a command and stream output live to terminal
9
+ function runLive(command, args = []) {
10
+ logger_1.logger.running(`${command} ${args.join(' ')}`);
11
+ const result = (0, child_process_1.spawnSync)(command, args, { stdio: 'inherit', shell: true });
12
+ if (result.status !== 0) {
13
+ throw new Error(`Command failed: ${command} ${args.join(' ')}`);
14
+ }
15
+ }
16
+ // Run a command silently and return the output as string
17
+ function runSilent(command, args = []) {
18
+ try {
19
+ const result = (0, child_process_1.spawnSync)(command, args, { stdio: 'pipe', shell: true });
20
+ return result.stdout?.toString().trim() ?? '';
21
+ }
22
+ catch {
23
+ return '';
24
+ }
25
+ }
26
+ // Check if a command/tool exists on the machine
27
+ function commandExists(command) {
28
+ try {
29
+ (0, child_process_1.execSync)(`${command} --version`, { stdio: 'pipe' });
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/utils/runner.ts"],"names":[],"mappings":";;AAIA,0BAMC;AAGD,8BAOC;AAGD,sCAOC;AA9BD,iDAAoD;AACpD,qCAAkC;AAElC,mDAAmD;AACnD,SAAgB,OAAO,CAAC,OAAe,EAAE,OAAiB,EAAE;IAC1D,eAAM,CAAC,OAAO,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,mBAAmB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,SAAgB,SAAS,CAAC,OAAe,EAAE,OAAiB,EAAE;IAC5D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,gDAAgD;AAChD,SAAgB,aAAa,CAAC,OAAe;IAC3C,IAAI,CAAC;QACH,IAAA,wBAAQ,EAAC,GAAG,OAAO,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,48 @@
1
+ {
2
+ "project_info": {
3
+ "project_number": "380729955105",
4
+ "project_id": "fire-pilot-rn123",
5
+ "storage_bucket": "fire-pilot-rn123.firebasestorage.app"
6
+ },
7
+ "client": [
8
+ {
9
+ "client_info": {
10
+ "mobilesdk_app_id": "1:380729955105:android:ad4075689600c8875de460",
11
+ "android_client_info": {
12
+ "package_name": "com.firepilot"
13
+ }
14
+ },
15
+ "oauth_client": [],
16
+ "api_key": [
17
+ {
18
+ "current_key": "AIzaSyANS4jZs8OFN7x4zcKJYRQZzELC-IXRIHE"
19
+ }
20
+ ],
21
+ "services": {
22
+ "appinvite_service": {
23
+ "other_platform_oauth_client": []
24
+ }
25
+ }
26
+ },
27
+ {
28
+ "client_info": {
29
+ "mobilesdk_app_id": "1:380729955105:android:c9d7bf1bd047d2025de460",
30
+ "android_client_info": {
31
+ "package_name": "com.firepilotlearn"
32
+ }
33
+ },
34
+ "oauth_client": [],
35
+ "api_key": [
36
+ {
37
+ "current_key": "AIzaSyANS4jZs8OFN7x4zcKJYRQZzELC-IXRIHE"
38
+ }
39
+ ],
40
+ "services": {
41
+ "appinvite_service": {
42
+ "other_platform_oauth_client": []
43
+ }
44
+ }
45
+ }
46
+ ],
47
+ "configuration_version": "1"
48
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "fire-pilot-rn",
3
+ "version": "1.0.0",
4
+ "description": "Elite Firebase setup orchestrator for React Native. Automates login, project creation, and SHA registration.",
5
+ "main": "build/index.js",
6
+ "bin": {
7
+ "fire-pilot-rn": "build/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "rimraf build && tsc",
11
+ "dev": "ts-node src/index.ts",
12
+ "start": "node build/index.js",
13
+ "prepare": "npm run build",
14
+ "postbuild": "chmod +x build/index.js"
15
+ },
16
+ "keywords": [
17
+ "firebase",
18
+ "react-native",
19
+ "cli",
20
+ "setup"
21
+ ],
22
+ "author": "Your Name",
23
+ "license": "MIT",
24
+ "readme": "README.md",
25
+ "homepage": "https://github.com/your-username/fire-pilot-rn#readme",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/your-username/fire-pilot-rn.git"
29
+ },
30
+ "bugs": {
31
+ "url": "https://github.com/your-username/fire-pilot-rn/issues"
32
+ },
33
+ "dependencies": {
34
+ "@react-native-firebase/app": "^24.0.0",
35
+ "@react-native-firebase/auth": "^24.0.0",
36
+ "@react-native-firebase/crashlytics": "^24.0.0",
37
+ "@react-native-firebase/firestore": "^24.0.0",
38
+ "chalk": "^4.1.2",
39
+ "commander": "^11.0.0",
40
+ "execa": "^5.1.1",
41
+ "inquirer": "^8.2.6",
42
+ "ora": "^5.4.1"
43
+ },
44
+ "devDependencies": {
45
+ "@types/inquirer": "^8.2.10",
46
+ "@types/node": "^20.0.0",
47
+ "rimraf": "^5.0.0",
48
+ "ts-node": "^10.9.1",
49
+ "typescript": "^5.0.0"
50
+ }
51
+ }
@@ -0,0 +1,80 @@
1
+ import inquirer from 'inquirer';
2
+ import { runLive } from '../utils/runner';
3
+ import { logger } from '../utils/logger';
4
+
5
+ // Always keep the core package in sync with installed feature packages.
6
+ const CORE_PACKAGE = '@react-native-firebase/app';
7
+
8
+ // All supported RN Firebase packages
9
+ const FEATURES: Record<string, { label: string; pkg: string; extra?: string }> = {
10
+ auth: { label: '🔐 Authentication', pkg: '@react-native-firebase/auth' },
11
+ firestore: { label: '🗄️ Firestore Database', pkg: '@react-native-firebase/firestore' },
12
+ storage: { label: '📦 Cloud Storage', pkg: '@react-native-firebase/storage' },
13
+ messaging: { label: '📲 Cloud Messaging (FCM)', pkg: '@react-native-firebase/messaging' },
14
+ analytics: { label: '📈 Analytics', pkg: '@react-native-firebase/analytics' },
15
+ crashlytics: { label: '💥 Crashlytics', pkg: '@react-native-firebase/crashlytics' },
16
+ database: { label: '⚡ Realtime Database', pkg: '@react-native-firebase/database' },
17
+ functions: { label: '☁️ Cloud Functions', pkg: '@react-native-firebase/functions' },
18
+ remote: { label: '🎛️ Remote Config', pkg: '@react-native-firebase/remote-config' },
19
+ perf: { label: '⏱️ Performance Monitoring', pkg: '@react-native-firebase/perf' },
20
+ };
21
+
22
+ export async function enableCommand(feature?: string): Promise<void> {
23
+ logger.title('Enable Firebase Feature');
24
+
25
+ let selectedKey = feature;
26
+
27
+ // ── If no feature passed, show interactive menu ──────────────
28
+ if (!selectedKey) {
29
+ const choices = Object.entries(FEATURES).map(([key, val]) => ({
30
+ name: val.label,
31
+ value: key,
32
+ }));
33
+
34
+ // Allow selecting multiple features at once
35
+ const { selected } = await inquirer.prompt([
36
+ {
37
+ type: 'checkbox',
38
+ name: 'selected',
39
+ message: 'Select Firebase features to enable (Space to select, Enter to confirm):',
40
+ choices,
41
+ validate: (val: string[]) =>
42
+ val.length > 0 ? true : 'Please select at least one feature',
43
+ },
44
+ ]);
45
+
46
+ // Install all selected features
47
+ for (const key of selected) {
48
+ await installFeature(key);
49
+ }
50
+ return;
51
+ }
52
+
53
+ // ── If feature passed directly (e.g. firebase enable auth) ───
54
+ if (!FEATURES[selectedKey]) {
55
+ logger.error(`Unknown feature: "${selectedKey}"`);
56
+ logger.info(`Available features: ${Object.keys(FEATURES).join(', ')}`);
57
+ process.exit(1);
58
+ }
59
+
60
+ await installFeature(selectedKey);
61
+ }
62
+
63
+ async function installFeature(key: string): Promise<void> {
64
+ const feature = FEATURES[key];
65
+ logger.step(`Installing ${feature.label}...`);
66
+ logger.info(`Package: ${feature.pkg}`);
67
+
68
+ // Step 1: upgrade the core package to the latest version first so it
69
+ // satisfies any peer dep the feature package requires.
70
+ logger.info(`Upgrading ${CORE_PACKAGE} to latest...`);
71
+ runLive('npm', ['install', `${CORE_PACKAGE}@latest`]);
72
+
73
+ // Step 2: now install the feature package against the upgraded core.
74
+ logger.info(`Installing ${feature.pkg}...`);
75
+ runLive('npm', ['install', feature.pkg]);
76
+
77
+ logger.success(`${feature.label} installed!`);
78
+ logger.info(`Docs: https://rnfirebase.io/${key === 'auth' ? 'auth' : key}`);
79
+ console.log('');
80
+ }