clawfire 0.4.2 → 0.4.4
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/cli.js +1 -1
- package/dist/{dev-server-65H4AQFS.js → dev-server-XLMLGSQP.js} +119 -34
- package/dist/dev.cjs +119 -34
- package/dist/dev.cjs.map +1 -1
- package/dist/dev.js +119 -34
- package/dist/dev.js.map +1 -1
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -1457,38 +1457,89 @@ async function checkCli(projectDir) {
|
|
|
1457
1457
|
return result;
|
|
1458
1458
|
}
|
|
1459
1459
|
async function fetchFirebaseSdkConfig(projectDir) {
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
return
|
|
1469
|
-
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1460
|
+
try {
|
|
1461
|
+
const output = await execWithTimeout(
|
|
1462
|
+
"firebase",
|
|
1463
|
+
["apps:sdkconfig", "web", "--json"],
|
|
1464
|
+
projectDir,
|
|
1465
|
+
15e3
|
|
1466
|
+
);
|
|
1467
|
+
const config = parseSdkConfigOutput(output);
|
|
1468
|
+
if (config) return config;
|
|
1469
|
+
} catch {
|
|
1470
|
+
}
|
|
1471
|
+
let webApps = [];
|
|
1472
|
+
try {
|
|
1473
|
+
const appsOutput = await execWithTimeout(
|
|
1474
|
+
"firebase",
|
|
1475
|
+
["apps:list", "--json"],
|
|
1476
|
+
projectDir,
|
|
1477
|
+
15e3
|
|
1478
|
+
);
|
|
1479
|
+
const appsData = JSON.parse(appsOutput);
|
|
1480
|
+
const allApps = appsData?.result || [];
|
|
1481
|
+
webApps = allApps.filter((a) => a.platform === "WEB").map((a) => ({
|
|
1482
|
+
appId: String(a.appId || ""),
|
|
1483
|
+
displayName: String(a.displayName || "")
|
|
1484
|
+
})).filter((a) => a.appId);
|
|
1485
|
+
} catch {
|
|
1486
|
+
throw new Error(
|
|
1487
|
+
"Failed to fetch Firebase SDK config. Make sure you are logged in and have an active project selected."
|
|
1488
|
+
);
|
|
1489
|
+
}
|
|
1490
|
+
if (webApps.length === 0) {
|
|
1491
|
+
throw new Error(
|
|
1492
|
+
"No web app registered in this Firebase project. Go to Firebase Console > Project Settings > General > Your apps > Add app (Web) to create one, then click Auto-fill again."
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
const appId = webApps[0].appId;
|
|
1496
|
+
try {
|
|
1497
|
+
const output = await execWithTimeout(
|
|
1498
|
+
"firebase",
|
|
1499
|
+
["apps:sdkconfig", "web", appId, "--json"],
|
|
1500
|
+
projectDir,
|
|
1501
|
+
15e3
|
|
1502
|
+
);
|
|
1503
|
+
const config = parseSdkConfigOutput(output);
|
|
1504
|
+
if (config) return config;
|
|
1505
|
+
} catch (err) {
|
|
1506
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
1507
|
+
throw new Error(`Failed to fetch config for web app ${appId}: ${msg}`);
|
|
1484
1508
|
}
|
|
1485
1509
|
throw new Error("Could not parse Firebase SDK config from CLI output");
|
|
1486
1510
|
}
|
|
1511
|
+
function parseSdkConfigOutput(output) {
|
|
1512
|
+
try {
|
|
1513
|
+
const data = JSON.parse(output);
|
|
1514
|
+
if (data?.result?.sdkConfig) {
|
|
1515
|
+
return data.result.sdkConfig;
|
|
1516
|
+
}
|
|
1517
|
+
if (data?.result?.fileContents) {
|
|
1518
|
+
const contents = data.result.fileContents;
|
|
1519
|
+
const config = {};
|
|
1520
|
+
const extract = (key) => {
|
|
1521
|
+
const match = contents.match(new RegExp(`"${key}"\\s*:\\s*"([^"]+)"`));
|
|
1522
|
+
return match ? match[1] : void 0;
|
|
1523
|
+
};
|
|
1524
|
+
config.apiKey = extract("apiKey");
|
|
1525
|
+
config.authDomain = extract("authDomain");
|
|
1526
|
+
config.projectId = extract("projectId");
|
|
1527
|
+
config.storageBucket = extract("storageBucket");
|
|
1528
|
+
config.messagingSenderId = extract("messagingSenderId");
|
|
1529
|
+
config.appId = extract("appId");
|
|
1530
|
+
if (config.apiKey || config.projectId) return config;
|
|
1531
|
+
}
|
|
1532
|
+
} catch {
|
|
1533
|
+
}
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1487
1536
|
function execWithTimeout(command, args, cwd, timeoutMs) {
|
|
1488
1537
|
return new Promise((resolve7, reject) => {
|
|
1489
|
-
const proc = execFile(command, args, { cwd, timeout: timeoutMs }, (err, stdout) => {
|
|
1538
|
+
const proc = execFile(command, args, { cwd, timeout: timeoutMs }, (err, stdout, stderr) => {
|
|
1490
1539
|
if (err) {
|
|
1491
|
-
|
|
1540
|
+
const detail = stderr?.trim() || stdout?.trim() || "";
|
|
1541
|
+
const enriched = new Error(`${err.message}${detail ? "\n" + detail : ""}`);
|
|
1542
|
+
reject(enriched);
|
|
1492
1543
|
} else {
|
|
1493
1544
|
resolve7(stdout);
|
|
1494
1545
|
}
|
|
@@ -1787,6 +1838,9 @@ function generateDashboardHtml(options) {
|
|
|
1787
1838
|
document.getElementById('step-' + i).style.display = 'none';
|
|
1788
1839
|
}
|
|
1789
1840
|
document.getElementById('setup-done').style.display = 'none';
|
|
1841
|
+
// Reset login UI state from previous interactions
|
|
1842
|
+
document.getElementById('login-waiting').style.display = 'none';
|
|
1843
|
+
document.getElementById('login-result').style.display = 'none';
|
|
1790
1844
|
|
|
1791
1845
|
if (status.nextStep === 'done') {
|
|
1792
1846
|
// All done!
|
|
@@ -1950,7 +2004,12 @@ function generateDashboardHtml(options) {
|
|
|
1950
2004
|
var result = document.getElementById('login-result');
|
|
1951
2005
|
result.textContent = 'Login successful! Logged in as ' + status.auth.user;
|
|
1952
2006
|
result.style.cssText = 'display:block;margin-top:8px;font-size:13px;padding:8px 12px;border-radius:6px;background:#0a1a0a;border:1px solid #22c55e;color:#22c55e;';
|
|
1953
|
-
|
|
2007
|
+
// Wait for token to fully settle, then refresh wizard + force-load projects
|
|
2008
|
+
setTimeout(function() {
|
|
2009
|
+
refreshSetupStatus();
|
|
2010
|
+
// Extra delay for project list \u2014 Firebase CLI needs time after fresh login
|
|
2011
|
+
setTimeout(function() { loadProjectList(''); }, 2500);
|
|
2012
|
+
}, 2000);
|
|
1954
2013
|
}
|
|
1955
2014
|
})
|
|
1956
2015
|
.catch(function() {});
|
|
@@ -1958,7 +2017,8 @@ function generateDashboardHtml(options) {
|
|
|
1958
2017
|
}
|
|
1959
2018
|
|
|
1960
2019
|
// \u2500\u2500\u2500 Step 3: Project Selection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1961
|
-
function loadProjectList(currentProjectId) {
|
|
2020
|
+
function loadProjectList(currentProjectId, retryCount) {
|
|
2021
|
+
retryCount = retryCount || 0;
|
|
1962
2022
|
var select = document.getElementById('project-select');
|
|
1963
2023
|
select.innerHTML = '<option value="">Loading projects...</option>';
|
|
1964
2024
|
select.disabled = true;
|
|
@@ -1968,10 +2028,21 @@ function generateDashboardHtml(options) {
|
|
|
1968
2028
|
.then(function(data) {
|
|
1969
2029
|
select.innerHTML = '';
|
|
1970
2030
|
if (data.error) {
|
|
2031
|
+
// Auto-retry up to 2 times on error (token might not be ready yet after fresh login)
|
|
2032
|
+
if (retryCount < 2) {
|
|
2033
|
+
select.innerHTML = '<option value="">Loading projects... (retry)</option>';
|
|
2034
|
+
setTimeout(function() { loadProjectList(currentProjectId, retryCount + 1); }, 3000);
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
1971
2037
|
select.innerHTML = '<option value="">Error: ' + escHtml(data.error) + '</option>';
|
|
1972
2038
|
return;
|
|
1973
2039
|
}
|
|
1974
2040
|
if (!data.projects || data.projects.length === 0) {
|
|
2041
|
+
if (retryCount < 2) {
|
|
2042
|
+
select.innerHTML = '<option value="">Loading projects... (retry)</option>';
|
|
2043
|
+
setTimeout(function() { loadProjectList(currentProjectId, retryCount + 1); }, 3000);
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
1975
2046
|
select.innerHTML = '<option value="">No projects found</option>';
|
|
1976
2047
|
return;
|
|
1977
2048
|
}
|
|
@@ -1987,6 +2058,11 @@ function generateDashboardHtml(options) {
|
|
|
1987
2058
|
select.disabled = false;
|
|
1988
2059
|
})
|
|
1989
2060
|
.catch(function(err) {
|
|
2061
|
+
if (retryCount < 2) {
|
|
2062
|
+
select.innerHTML = '<option value="">Loading projects... (retry)</option>';
|
|
2063
|
+
setTimeout(function() { loadProjectList(currentProjectId, retryCount + 1); }, 3000);
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
1990
2066
|
select.innerHTML = '<option value="">Failed to load</option>';
|
|
1991
2067
|
});
|
|
1992
2068
|
}
|
|
@@ -2212,7 +2288,12 @@ function generateDashboardHtml(options) {
|
|
|
2212
2288
|
if (wizStatus) wizStatus.style.display = 'none';
|
|
2213
2289
|
|
|
2214
2290
|
fetch(API + '/__dev/firebase-sdk-config')
|
|
2215
|
-
.then(function(r) {
|
|
2291
|
+
.then(function(r) {
|
|
2292
|
+
if (!r.ok) {
|
|
2293
|
+
return r.json().catch(function() { return { error: 'Server error (' + r.status + ')' }; });
|
|
2294
|
+
}
|
|
2295
|
+
return r.json();
|
|
2296
|
+
})
|
|
2216
2297
|
.then(function(data) {
|
|
2217
2298
|
if (data.error) {
|
|
2218
2299
|
showAutoFillResult(false, data.error);
|
|
@@ -2528,13 +2609,16 @@ var FirebaseSetup = class {
|
|
|
2528
2609
|
`cd "${this.projectDir}"`,
|
|
2529
2610
|
cmd,
|
|
2530
2611
|
'echo ""',
|
|
2531
|
-
'echo "Login complete!
|
|
2532
|
-
|
|
2612
|
+
'echo "Login complete! Closing in 3 seconds..."',
|
|
2613
|
+
"sleep 3",
|
|
2614
|
+
// Spawn osascript in background to close this specific terminal window, then exit
|
|
2615
|
+
`(sleep 1 && osascript -e 'tell application "Terminal" to close (every window whose name contains "clawfire-firebase-login")' 2>/dev/null) &`,
|
|
2616
|
+
"exit 0"
|
|
2533
2617
|
].join("\n"), { mode: 493 });
|
|
2534
2618
|
const child = spawn("open", [scriptPath], { detached: true, stdio: "ignore" });
|
|
2535
2619
|
child.unref();
|
|
2536
2620
|
} else if (os === "win32") {
|
|
2537
|
-
const child = spawn("cmd", ["/c", "start", "cmd", "/
|
|
2621
|
+
const child = spawn("cmd", ["/c", "start", "cmd", "/c", `${cmd} && timeout /t 3 >nul`], {
|
|
2538
2622
|
cwd: this.projectDir,
|
|
2539
2623
|
detached: true,
|
|
2540
2624
|
stdio: "ignore"
|
|
@@ -2547,8 +2631,9 @@ var FirebaseSetup = class {
|
|
|
2547
2631
|
`cd "${this.projectDir}"`,
|
|
2548
2632
|
cmd,
|
|
2549
2633
|
'echo ""',
|
|
2550
|
-
'echo "Login complete!
|
|
2551
|
-
|
|
2634
|
+
'echo "Login complete! Closing in 3 seconds..."',
|
|
2635
|
+
"sleep 3",
|
|
2636
|
+
"exit 0"
|
|
2552
2637
|
].join("\n"), { mode: 493 });
|
|
2553
2638
|
const terminals = [
|
|
2554
2639
|
{ cmd: "x-terminal-emulator", args: ["-e", scriptPath] },
|