firebase-os 1.1.7 → 1.1.8
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/firebase-os.cjs.js +3 -3
- package/dist/firebase-os.es.js +1037 -1022
- package/package.json +1 -1
- package/scripts/postinstall.js +30 -16
- package/src/FirebaseOS.tsx +8 -2
- package/src/pages/Setup.tsx +15 -9
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -191,32 +191,46 @@ const viteConfigPath = path.join(consumerRoot, 'vite.config.ts');
|
|
|
191
191
|
if (fs.existsSync(viteConfigPath)) {
|
|
192
192
|
let viteConfig = fs.readFileSync(viteConfigPath, 'utf8');
|
|
193
193
|
if (!viteConfig.includes('@tailwindcss/vite')) {
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
// Build the patched file with real newlines (not escaped \n literals)
|
|
195
|
+
const importLine = "import tailwindcss from '@tailwindcss/vite';";
|
|
196
|
+
viteConfig = importLine + '\n' + viteConfig;
|
|
197
|
+
viteConfig = viteConfig.replace(
|
|
198
|
+
'plugins: [',
|
|
199
|
+
'plugins: [\n tailwindcss(),'
|
|
200
|
+
);
|
|
196
201
|
fs.writeFileSync(viteConfigPath, viteConfig);
|
|
197
202
|
console.log(' ✓ Patched vite.config.ts to enable Tailwind CSS v4');
|
|
198
203
|
}
|
|
199
204
|
}
|
|
200
205
|
|
|
201
|
-
// ── 6. Create .env file with placeholders
|
|
206
|
+
// ── 6. Create .env file with empty placeholders ────────────────────────────
|
|
202
207
|
const envPath = path.join(consumerRoot, '.env');
|
|
203
208
|
if (!fs.existsSync(envPath)) {
|
|
204
209
|
const envContent = `# 🔥 Firebase OS Configuration
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
# Fill in each value below with your Firebase Web App credentials.
|
|
211
|
+
# Find them in Firebase Console -> Project Settings -> General -> Your Apps
|
|
212
|
+
# Leave values empty until you are ready — the app will show a Setup page.
|
|
213
|
+
# After filling them in, restart the dev server (npm run dev).
|
|
214
|
+
|
|
215
|
+
# Your Firebase API Key (e.g. AIzaSyD...)
|
|
216
|
+
VITE_FIREBASE_API_KEY=
|
|
217
|
+
# Your Firebase Auth Domain (e.g. myproject.firebaseapp.com)
|
|
218
|
+
VITE_FIREBASE_AUTH_DOMAIN=
|
|
219
|
+
# Your Firebase Project ID (e.g. myproject)
|
|
220
|
+
VITE_FIREBASE_PROJECT_ID=
|
|
221
|
+
# Your Firebase Storage Bucket (e.g. myproject.firebasestorage.app)
|
|
222
|
+
VITE_FIREBASE_STORAGE_BUCKET=
|
|
223
|
+
# Your Firebase Messaging Sender ID (e.g. 123456789012)
|
|
224
|
+
VITE_FIREBASE_MESSAGING_SENDER_ID=
|
|
225
|
+
# Your Firebase App ID (e.g. 1:123456789012:web:abcdef123456)
|
|
226
|
+
VITE_FIREBASE_APP_ID=
|
|
227
|
+
|
|
228
|
+
# Comma-separated list of admin email addresses (these users get admin role on first registration)
|
|
229
|
+
# Example: you@email.com,colleague@email.com
|
|
230
|
+
VITE_ADMIN_EMAILS=
|
|
217
231
|
`;
|
|
218
232
|
fs.writeFileSync(envPath, envContent);
|
|
219
|
-
console.log(' ✓ Created .env template');
|
|
233
|
+
console.log(' ✓ Created .env template (fill in your Firebase credentials)');
|
|
220
234
|
}
|
|
221
235
|
|
|
222
236
|
console.log('\n[firebase-os] 🎉 Hybrid Setup complete! You now have full control over styling and configs.\n');
|
package/src/FirebaseOS.tsx
CHANGED
|
@@ -53,8 +53,14 @@ export interface FirebaseOSProps {
|
|
|
53
53
|
export function FirebaseOS(props: FirebaseOSProps) {
|
|
54
54
|
// If the consumer passed firebaseConfig as props, initialize Firebase
|
|
55
55
|
// before any child component tries to use auth/db/storage.
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// Guard: only initialize when real credentials are present (not empty strings).
|
|
57
|
+
const fc = props.firebaseConfig;
|
|
58
|
+
const hasRealConfig = fc &&
|
|
59
|
+
fc.apiKey && fc.apiKey.trim() !== '' &&
|
|
60
|
+
fc.projectId && fc.projectId.trim() !== '';
|
|
61
|
+
|
|
62
|
+
if (hasRealConfig) {
|
|
63
|
+
initializeFirebase(fc);
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
const config: FirebaseOSConfig = {
|
package/src/pages/Setup.tsx
CHANGED
|
@@ -60,21 +60,22 @@ function getEnvVal(key: string): string {
|
|
|
60
60
|
// Environment key status
|
|
61
61
|
export function getEnvStatus() {
|
|
62
62
|
const missing: string[] = [];
|
|
63
|
+
const empty: string[] = [];
|
|
63
64
|
for (const { key, label } of REQUIRED_KEYS) {
|
|
64
65
|
const v = getEnvVal(key);
|
|
65
|
-
if (!v
|
|
66
|
-
console.log('Missing key:', key, v);
|
|
66
|
+
if (!v) {
|
|
67
67
|
missing.push(label);
|
|
68
|
-
} else {
|
|
69
|
-
|
|
68
|
+
} else if (v.trim() === '') {
|
|
69
|
+
empty.push(label);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
const adminEmails = getEnvVal('VITE_ADMIN_EMAILS');
|
|
74
74
|
const missingAdminEmails = !adminEmails || adminEmails.trim() === '';
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
// Combine missing + empty for the overall check
|
|
77
|
+
const allMissing = [...missing, ...empty];
|
|
78
|
+
return { allSet: allMissing.length === 0, missing: allMissing, empty, missingAdminEmails };
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
export function isSetupComplete(): boolean {
|
|
@@ -171,7 +172,7 @@ export function Setup({ standalone }: SetupProps) {
|
|
|
171
172
|
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
172
173
|
});
|
|
173
174
|
|
|
174
|
-
const [verifyResult, setVerifyResult] = useState<{ missing: string[]; missingAdminEmails?: boolean } | null>(null);
|
|
175
|
+
const [verifyResult, setVerifyResult] = useState<{ missing: string[]; empty?: string[]; missingAdminEmails?: boolean } | null>(null);
|
|
175
176
|
const [isVerifying, setIsVerifying] = useState(false);
|
|
176
177
|
|
|
177
178
|
// Only manage the data-theme attribute and favicon when standalone (no ThemeContext)
|
|
@@ -199,7 +200,7 @@ export function Setup({ standalone }: SetupProps) {
|
|
|
199
200
|
setVerifyResult(null);
|
|
200
201
|
setTimeout(() => {
|
|
201
202
|
const status = getEnvStatus();
|
|
202
|
-
setVerifyResult({ missing: status.missing, missingAdminEmails: status.missingAdminEmails });
|
|
203
|
+
setVerifyResult({ missing: status.missing, empty: status.empty, missingAdminEmails: status.missingAdminEmails });
|
|
203
204
|
if (status.allSet) {
|
|
204
205
|
setTimeout(() => { window.location.href = '/'; }, 1800);
|
|
205
206
|
}
|
|
@@ -285,7 +286,12 @@ export function Setup({ standalone }: SetupProps) {
|
|
|
285
286
|
<div className="w-8 h-8 rounded-full bg-red-500/10 border border-red-500/20 flex items-center justify-center shrink-0">
|
|
286
287
|
<AlertCircle className="w-4 h-4 text-red-500" />
|
|
287
288
|
</div>
|
|
288
|
-
<span className="font-bold text-foreground/70">
|
|
289
|
+
<span className="font-bold text-foreground/70">
|
|
290
|
+
{verifyResult.empty && verifyResult.empty.length > 0
|
|
291
|
+
? <>These values are <span className="text-red-500">empty</span> — fill them in your <code className="text-accent text-[12px]">.env</code> file and restart the dev server</>
|
|
292
|
+
: <>Missing values — update <code className="text-accent text-[12px]">.env</code> and restart dev server</>
|
|
293
|
+
}
|
|
294
|
+
</span>
|
|
289
295
|
</div>
|
|
290
296
|
<div className="flex flex-wrap gap-1.5 ml-10">
|
|
291
297
|
{verifyResult.missing.map(m => (
|