firebase-os 1.1.7 → 1.1.9
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 +1039 -1024
- package/package.json +1 -1
- package/scripts/postinstall.js +41 -21
- package/src/FirebaseOS.tsx +8 -2
- package/src/pages/Setup.tsx +17 -11
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -60,14 +60,20 @@ for (const file of cssFiles) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
// ── 2.
|
|
63
|
+
// ── 2. Rewrite main.tsx — import library + theme CSS at the entry point ─────
|
|
64
64
|
const mainPath = path.join(srcDir, 'main.tsx');
|
|
65
65
|
if (fs.existsSync(mainPath)) {
|
|
66
66
|
const mainContent = fs.readFileSync(mainPath, 'utf8');
|
|
67
|
-
//
|
|
68
|
-
if (mainContent.includes("import './index.css'") || mainContent.includes('import "./index.css"')) {
|
|
67
|
+
// Rewrite if it has the default Vite CSS import OR if it doesn't have our library CSS
|
|
68
|
+
if (mainContent.includes("import './index.css'") || mainContent.includes('import "./index.css"') || !mainContent.includes('firebase-os')) {
|
|
69
69
|
const clean = `import { StrictMode } from 'react'
|
|
70
70
|
import { createRoot } from 'react-dom/client'
|
|
71
|
+
|
|
72
|
+
// Firebase OS — compiled library styles (Tailwind utilities, components, layouts)
|
|
73
|
+
import 'firebase-os/styles.css'
|
|
74
|
+
// Firebase OS — local theme overrides (CSS variables, data-theme, custom styles)
|
|
75
|
+
import './firebase-os/theme.css'
|
|
76
|
+
|
|
71
77
|
import App from './App.tsx'
|
|
72
78
|
|
|
73
79
|
createRoot(document.getElementById('root')!).render(
|
|
@@ -77,7 +83,7 @@ createRoot(document.getElementById('root')!).render(
|
|
|
77
83
|
)
|
|
78
84
|
`;
|
|
79
85
|
fs.writeFileSync(mainPath, clean);
|
|
80
|
-
console.log(' ✓ Patched main.tsx
|
|
86
|
+
console.log(' ✓ Patched main.tsx with Firebase OS styles');
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
|
|
@@ -120,9 +126,9 @@ if (fs.existsSync(sourceHomePath)) {
|
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
// ── 4. Write App.tsx with Hybrid Overrides Wired Up ───────────────────────
|
|
129
|
+
// Note: CSS imports are in main.tsx (entry point) for correct load ordering.
|
|
123
130
|
const appPath = path.join(srcDir, 'App.tsx');
|
|
124
131
|
const appContent = `import { FirebaseOS } from 'firebase-os';
|
|
125
|
-
import './firebase-os/theme.css';
|
|
126
132
|
|
|
127
133
|
// Local Hybrid Overrides
|
|
128
134
|
import { Home } from './firebase-os/Home';
|
|
@@ -191,32 +197,46 @@ const viteConfigPath = path.join(consumerRoot, 'vite.config.ts');
|
|
|
191
197
|
if (fs.existsSync(viteConfigPath)) {
|
|
192
198
|
let viteConfig = fs.readFileSync(viteConfigPath, 'utf8');
|
|
193
199
|
if (!viteConfig.includes('@tailwindcss/vite')) {
|
|
194
|
-
|
|
195
|
-
|
|
200
|
+
// Build the patched file with real newlines (not escaped \n literals)
|
|
201
|
+
const importLine = "import tailwindcss from '@tailwindcss/vite';";
|
|
202
|
+
viteConfig = importLine + '\n' + viteConfig;
|
|
203
|
+
viteConfig = viteConfig.replace(
|
|
204
|
+
'plugins: [',
|
|
205
|
+
'plugins: [\n tailwindcss(),'
|
|
206
|
+
);
|
|
196
207
|
fs.writeFileSync(viteConfigPath, viteConfig);
|
|
197
208
|
console.log(' ✓ Patched vite.config.ts to enable Tailwind CSS v4');
|
|
198
209
|
}
|
|
199
210
|
}
|
|
200
211
|
|
|
201
|
-
// ── 6. Create .env file with placeholders
|
|
212
|
+
// ── 6. Create .env file with empty placeholders ────────────────────────────
|
|
202
213
|
const envPath = path.join(consumerRoot, '.env');
|
|
203
214
|
if (!fs.existsSync(envPath)) {
|
|
204
215
|
const envContent = `# 🔥 Firebase OS Configuration
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
216
|
+
# Fill in each value below with your Firebase Web App credentials.
|
|
217
|
+
# Find them in Firebase Console -> Project Settings -> General -> Your Apps
|
|
218
|
+
# Leave values empty until you are ready — the app will show a Setup page.
|
|
219
|
+
# After filling them in, restart the dev server (npm run dev).
|
|
220
|
+
|
|
221
|
+
# Your Firebase API Key (e.g. AIzaSyD...)
|
|
222
|
+
VITE_FIREBASE_API_KEY=
|
|
223
|
+
# Your Firebase Auth Domain (e.g. myproject.firebaseapp.com)
|
|
224
|
+
VITE_FIREBASE_AUTH_DOMAIN=
|
|
225
|
+
# Your Firebase Project ID (e.g. myproject)
|
|
226
|
+
VITE_FIREBASE_PROJECT_ID=
|
|
227
|
+
# Your Firebase Storage Bucket (e.g. myproject.firebasestorage.app)
|
|
228
|
+
VITE_FIREBASE_STORAGE_BUCKET=
|
|
229
|
+
# Your Firebase Messaging Sender ID (e.g. 123456789012)
|
|
230
|
+
VITE_FIREBASE_MESSAGING_SENDER_ID=
|
|
231
|
+
# Your Firebase App ID (e.g. 1:123456789012:web:abcdef123456)
|
|
232
|
+
VITE_FIREBASE_APP_ID=
|
|
233
|
+
|
|
234
|
+
# Comma-separated list of admin email addresses (these users get admin role on first registration)
|
|
235
|
+
# Example: you@email.com,colleague@email.com
|
|
236
|
+
VITE_ADMIN_EMAILS=
|
|
217
237
|
`;
|
|
218
238
|
fs.writeFileSync(envPath, envContent);
|
|
219
|
-
console.log(' ✓ Created .env template');
|
|
239
|
+
console.log(' ✓ Created .env template (fill in your Firebase credentials)');
|
|
220
240
|
}
|
|
221
241
|
|
|
222
242
|
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
|
}
|
|
@@ -232,8 +233,8 @@ export function Setup({ standalone }: SetupProps) {
|
|
|
232
233
|
className="glass-panel border border-[var(--panel-border)] rounded-3xl p-6 md:p-10 shadow-2xl relative overflow-hidden bg-background flex flex-col"
|
|
233
234
|
>
|
|
234
235
|
{/* Panel header with support buttons */}
|
|
235
|
-
<div className="
|
|
236
|
-
<div className="flex
|
|
236
|
+
<div className="mb-8 pb-6 border-b border-[var(--panel-border)]/50 relative z-10">
|
|
237
|
+
<div className="flex items-start justify-between gap-4">
|
|
237
238
|
<div>
|
|
238
239
|
<h2 className="text-xl font-extrabold text-foreground tracking-tight">Firebase Configuration</h2>
|
|
239
240
|
<p className="text-[14px] font-medium text-foreground/50 mt-2 leading-relaxed">
|
|
@@ -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 => (
|