clawfire 0.6.14 → 0.6.16

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 CHANGED
@@ -269,7 +269,7 @@ async function runDevServer() {
269
269
  const port = portArg ? parseInt(portArg.split("=")[1], 10) : 3e3;
270
270
  const apiPort = apiPortArg ? parseInt(apiPortArg.split("=")[1], 10) : 3456;
271
271
  const noHotReload = args.includes("--no-hot-reload");
272
- const { startDevServer } = await import("./dev-server-IKWE6UJT.js");
272
+ const { startDevServer } = await import("./dev-server-FYHT3WN5.js");
273
273
  await startDevServer({
274
274
  projectDir,
275
275
  port,
@@ -769,6 +769,7 @@ var PageCompiler = class {
769
769
  try {
770
770
  const compiled = this.compile(fullPath);
771
771
  let html = compiled.html;
772
+ html = this.sanitizeForProduction(html);
772
773
  if (scriptToInject) {
773
774
  if (html.includes("</body>")) {
774
775
  html = html.replace("</body>", scriptToInject + "\n</body>");
@@ -797,6 +798,18 @@ var PageCompiler = class {
797
798
  walk(this.pagesDir);
798
799
  return { pages, errors };
799
800
  }
801
+ // ─── Production Sanitization ─────────────────────────────────────
802
+ /**
803
+ * Remove dev-only content from production builds:
804
+ * - Sections wrapped in <!-- dev-only:start --> / <!-- dev-only:end -->
805
+ * - Links to http://localhost (API Playground, dev dashboard, etc.)
806
+ */
807
+ sanitizeForProduction(html) {
808
+ html = html.replace(/<!--\s*dev-only:start\s*-->[\s\S]*?<!--\s*dev-only:end\s*-->/g, "");
809
+ html = html.replace(/<a\s[^>]*href="http:\/\/localhost[^"]*"[^>]*>[\s\S]*?<\/a>/g, "");
810
+ html = html.replace(/\n{3,}/g, "\n\n");
811
+ return html;
812
+ }
800
813
  // ─── Internal Methods ────────────────────────────────────────────
801
814
  /**
802
815
  * Extract <!-- @key: value --> metadata from HTML.
@@ -1465,9 +1478,9 @@ function generateDashboardHtml(options) {
1465
1478
  <div style="margin-bottom:6px;"><strong style="color:#fbbf24;">Current Plan:</strong> <span style="color:#ef4444;">Spark (Free)</span></div>
1466
1479
  <div style="margin-bottom:6px;"><strong style="color:#fbbf24;">Required Plan:</strong> <span style="color:#22c55e;">Blaze (Pay-as-you-go)</span></div>
1467
1480
  <div style="margin-bottom:10px;color:#a3a3a3;font-size:12px;">
1468
- Static pages (HTML/CSS/JS) are deployed and working.<br>
1481
+ Static pages (HTML/CSS/JS) are deployed and live.<br>
1469
1482
  API routes (<code style="background:#2a2a2a;padding:2px 6px;border-radius:3px;color:#f97316;">/api/*</code>) require Cloud Functions, which need the Blaze plan.<br>
1470
- Blaze plan has a generous free tier \u2014 you only pay for actual usage beyond free limits.
1483
+ Blaze plan has a generous free tier \u2014 you only pay for usage beyond free limits.
1471
1484
  </div>
1472
1485
  <a id="deploy-upgrade-link" href="#" target="_blank" style="display:inline-block;padding:8px 16px;background:#f59e0b;color:#000;border-radius:6px;font-size:13px;font-weight:700;text-decoration:none;">
1473
1486
  Upgrade to Blaze Plan &#8594;
@@ -2354,13 +2367,12 @@ function generateDashboardHtml(options) {
2354
2367
  var btn = document.getElementById('deploy-hosting-btn');
2355
2368
  var status = document.getElementById('deploy-hosting-status');
2356
2369
  var urlBox = document.getElementById('deploy-hosting-url');
2370
+ var billingNote = document.getElementById('deploy-billing-note');
2357
2371
  btn.disabled = true;
2358
2372
  btn.textContent = 'Deploying...';
2359
- status.textContent = 'Deploying to Firebase Hosting... This may take up to 2 minutes.';
2373
+ status.textContent = 'Deploying to Firebase Hosting... This may take up to 3 minutes.';
2360
2374
  status.style.cssText = 'display:block;margin-top:10px;font-size:13px;padding:10px 14px;border-radius:6px;background:#0a0a1a;border:1px solid #3b82f6;color:#3b82f6;';
2361
2375
  urlBox.style.display = 'none';
2362
-
2363
- var billingNote = document.getElementById('deploy-billing-note');
2364
2376
  billingNote.style.display = 'none';
2365
2377
 
2366
2378
  fetch(API + '/__dev/deploy/hosting', { method: 'POST' })
@@ -2375,18 +2387,17 @@ function generateDashboardHtml(options) {
2375
2387
  link.textContent = data.url;
2376
2388
  urlBox.style.display = 'block';
2377
2389
  }
2378
- // Show Blaze plan notice if needed
2390
+ // Show Blaze plan notice when functions deploy failed
2379
2391
  if (data.blazeRequired) {
2380
2392
  billingNote.style.display = 'block';
2381
2393
  if (data.upgradeUrl) {
2382
- var upgradeLink = document.getElementById('deploy-upgrade-link');
2383
- upgradeLink.href = data.upgradeUrl;
2394
+ document.getElementById('deploy-upgrade-link').href = data.upgradeUrl;
2384
2395
  }
2385
2396
  }
2386
2397
  } else {
2387
2398
  status.textContent = data.message;
2388
2399
  status.style.cssText = 'display:block;margin-top:10px;font-size:13px;padding:10px 14px;border-radius:6px;background:#1c0808;border:1px solid #ef4444;color:#ef4444;';
2389
- // Check if error is about billing \u2014 show upgrade notice
2400
+ // Also check if error is billing-related
2390
2401
  var errMsg = (data.message || '').toLowerCase();
2391
2402
  if (errMsg.indexOf('blaze') >= 0 || errMsg.indexOf('pay-as-you-go') >= 0 || errMsg.indexOf('upgrade') >= 0 || errMsg.indexOf('artifactregistry') >= 0) {
2392
2403
  billingNote.style.display = 'block';
@@ -3421,7 +3432,8 @@ https://console.developers.google.com/apis/api/firestore.googleapis.com/overview
3421
3432
  return new Promise((resolve6, reject) => {
3422
3433
  const proc = execFile2(command, args, { cwd: cwd || this.projectDir, timeout: timeoutMs }, (err, stdout, stderr) => {
3423
3434
  if (err) {
3424
- const detail = stderr?.trim() || stdout?.trim() || "";
3435
+ const parts = [stderr?.trim(), stdout?.trim()].filter(Boolean);
3436
+ const detail = parts.join("\n");
3425
3437
  const enriched = new Error(`${err.message}${detail ? "\n" + detail : ""}`);
3426
3438
  reject(enriched);
3427
3439
  } else {
@@ -4650,45 +4662,38 @@ ${liveReloadScript}
4650
4662
  }
4651
4663
  steps.push("Hosting deployed");
4652
4664
  let blazeRequired = false;
4653
- let projectId = "";
4654
4665
  if (deployFunctions) {
4655
4666
  console.log(" Deploying functions...");
4656
4667
  const funcResult = await this.firebaseSetup.deployHosting("functions");
4657
4668
  if (funcResult.success) {
4658
- console.log(` \x1B[32m\u2713\x1B[0m Functions deployed`);
4669
+ console.log(" \x1B[32m\u2713\x1B[0m Functions deployed");
4659
4670
  steps.push("Functions deployed");
4660
4671
  } else {
4661
- const msg = funcResult.message.toLowerCase();
4662
- if (msg.includes("blaze") || msg.includes("pay-as-you-go") || msg.includes("upgrade") || msg.includes("billing") || msg.includes("artifactregistry")) {
4672
+ const errMsg = (funcResult.message || "").toLowerCase();
4673
+ const isBillingError = ["billing", "blaze", "pay-as-you-go", "upgrade your project", "budget"].some((kw) => errMsg.includes(kw));
4674
+ if (isBillingError) {
4663
4675
  blazeRequired = true;
4664
- const state = this.firebaseSetup.loadState();
4665
- projectId = state.projectId || firebaseConfig.projectId || "";
4666
- console.log(" \x1B[33m\u26A0\x1B[0m Functions require Blaze (pay-as-you-go) plan");
4676
+ console.log(" \x1B[33m\u26A0\x1B[0m Functions deploy failed (Blaze plan required)");
4667
4677
  steps.push("Functions skipped (Blaze plan required)");
4668
4678
  } else {
4669
4679
  console.log(` \x1B[31m\u2717\x1B[0m Functions deploy failed: ${funcResult.message}`);
4670
- steps.push("Functions deploy failed");
4680
+ steps.push(`Functions deploy failed: ${funcResult.message}`);
4671
4681
  }
4672
4682
  }
4673
4683
  }
4674
4684
  clearFirebaseStatusCache();
4685
+ const state = this.firebaseSetup.loadState();
4686
+ const projectId = state.projectId || firebaseConfig.projectId || "";
4687
+ const upgradeUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/usage/details` : "https://console.firebase.google.com";
4675
4688
  const stepsStr = steps.length > 0 ? ` (${steps.join(", ")})` : "";
4676
- if (blazeRequired) {
4677
- const upgradeUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/usage/details` : "https://console.firebase.google.com";
4678
- sendJson({
4679
- success: true,
4680
- url: hostingResult.url,
4681
- blazeRequired: true,
4682
- upgradeUrl,
4683
- message: `Hosting deployed successfully!${stepsStr}`,
4684
- billingNote: `Static pages are live, but API routes (/api/*) require Cloud Functions which need the Blaze (pay-as-you-go) plan. Upgrade at: ${upgradeUrl}`
4685
- });
4686
- } else {
4687
- sendJson({
4688
- ...hostingResult,
4689
- message: hostingResult.message + stepsStr
4690
- });
4691
- }
4689
+ sendJson({
4690
+ success: true,
4691
+ url: hostingResult.url,
4692
+ blazeRequired,
4693
+ upgradeUrl: blazeRequired ? upgradeUrl : void 0,
4694
+ message: `Hosting deployed successfully!${stepsStr}`,
4695
+ billingNote: blazeRequired ? `Static pages are live! But API routes (/api/*) need Cloud Functions, which require the Blaze (pay-as-you-go) plan. Upgrade: ${upgradeUrl}` : void 0
4696
+ });
4692
4697
  } catch (err) {
4693
4698
  sendJson({ success: false, message: err instanceof Error ? err.message : "Failed" }, 500);
4694
4699
  }
package/dist/dev.cjs CHANGED
@@ -1181,6 +1181,7 @@ var PageCompiler = class {
1181
1181
  try {
1182
1182
  const compiled = this.compile(fullPath);
1183
1183
  let html = compiled.html;
1184
+ html = this.sanitizeForProduction(html);
1184
1185
  if (scriptToInject) {
1185
1186
  if (html.includes("</body>")) {
1186
1187
  html = html.replace("</body>", scriptToInject + "\n</body>");
@@ -1209,6 +1210,18 @@ var PageCompiler = class {
1209
1210
  walk(this.pagesDir);
1210
1211
  return { pages, errors };
1211
1212
  }
1213
+ // ─── Production Sanitization ─────────────────────────────────────
1214
+ /**
1215
+ * Remove dev-only content from production builds:
1216
+ * - Sections wrapped in <!-- dev-only:start --> / <!-- dev-only:end -->
1217
+ * - Links to http://localhost (API Playground, dev dashboard, etc.)
1218
+ */
1219
+ sanitizeForProduction(html) {
1220
+ html = html.replace(/<!--\s*dev-only:start\s*-->[\s\S]*?<!--\s*dev-only:end\s*-->/g, "");
1221
+ html = html.replace(/<a\s[^>]*href="http:\/\/localhost[^"]*"[^>]*>[\s\S]*?<\/a>/g, "");
1222
+ html = html.replace(/\n{3,}/g, "\n\n");
1223
+ return html;
1224
+ }
1212
1225
  // ─── Internal Methods ────────────────────────────────────────────
1213
1226
  /**
1214
1227
  * Extract <!-- @key: value --> metadata from HTML.
@@ -1877,9 +1890,9 @@ function generateDashboardHtml(options) {
1877
1890
  <div style="margin-bottom:6px;"><strong style="color:#fbbf24;">Current Plan:</strong> <span style="color:#ef4444;">Spark (Free)</span></div>
1878
1891
  <div style="margin-bottom:6px;"><strong style="color:#fbbf24;">Required Plan:</strong> <span style="color:#22c55e;">Blaze (Pay-as-you-go)</span></div>
1879
1892
  <div style="margin-bottom:10px;color:#a3a3a3;font-size:12px;">
1880
- Static pages (HTML/CSS/JS) are deployed and working.<br>
1893
+ Static pages (HTML/CSS/JS) are deployed and live.<br>
1881
1894
  API routes (<code style="background:#2a2a2a;padding:2px 6px;border-radius:3px;color:#f97316;">/api/*</code>) require Cloud Functions, which need the Blaze plan.<br>
1882
- Blaze plan has a generous free tier \u2014 you only pay for actual usage beyond free limits.
1895
+ Blaze plan has a generous free tier \u2014 you only pay for usage beyond free limits.
1883
1896
  </div>
1884
1897
  <a id="deploy-upgrade-link" href="#" target="_blank" style="display:inline-block;padding:8px 16px;background:#f59e0b;color:#000;border-radius:6px;font-size:13px;font-weight:700;text-decoration:none;">
1885
1898
  Upgrade to Blaze Plan &#8594;
@@ -2766,13 +2779,12 @@ function generateDashboardHtml(options) {
2766
2779
  var btn = document.getElementById('deploy-hosting-btn');
2767
2780
  var status = document.getElementById('deploy-hosting-status');
2768
2781
  var urlBox = document.getElementById('deploy-hosting-url');
2782
+ var billingNote = document.getElementById('deploy-billing-note');
2769
2783
  btn.disabled = true;
2770
2784
  btn.textContent = 'Deploying...';
2771
- status.textContent = 'Deploying to Firebase Hosting... This may take up to 2 minutes.';
2785
+ status.textContent = 'Deploying to Firebase Hosting... This may take up to 3 minutes.';
2772
2786
  status.style.cssText = 'display:block;margin-top:10px;font-size:13px;padding:10px 14px;border-radius:6px;background:#0a0a1a;border:1px solid #3b82f6;color:#3b82f6;';
2773
2787
  urlBox.style.display = 'none';
2774
-
2775
- var billingNote = document.getElementById('deploy-billing-note');
2776
2788
  billingNote.style.display = 'none';
2777
2789
 
2778
2790
  fetch(API + '/__dev/deploy/hosting', { method: 'POST' })
@@ -2787,18 +2799,17 @@ function generateDashboardHtml(options) {
2787
2799
  link.textContent = data.url;
2788
2800
  urlBox.style.display = 'block';
2789
2801
  }
2790
- // Show Blaze plan notice if needed
2802
+ // Show Blaze plan notice when functions deploy failed
2791
2803
  if (data.blazeRequired) {
2792
2804
  billingNote.style.display = 'block';
2793
2805
  if (data.upgradeUrl) {
2794
- var upgradeLink = document.getElementById('deploy-upgrade-link');
2795
- upgradeLink.href = data.upgradeUrl;
2806
+ document.getElementById('deploy-upgrade-link').href = data.upgradeUrl;
2796
2807
  }
2797
2808
  }
2798
2809
  } else {
2799
2810
  status.textContent = data.message;
2800
2811
  status.style.cssText = 'display:block;margin-top:10px;font-size:13px;padding:10px 14px;border-radius:6px;background:#1c0808;border:1px solid #ef4444;color:#ef4444;';
2801
- // Check if error is about billing \u2014 show upgrade notice
2812
+ // Also check if error is billing-related
2802
2813
  var errMsg = (data.message || '').toLowerCase();
2803
2814
  if (errMsg.indexOf('blaze') >= 0 || errMsg.indexOf('pay-as-you-go') >= 0 || errMsg.indexOf('upgrade') >= 0 || errMsg.indexOf('artifactregistry') >= 0) {
2804
2815
  billingNote.style.display = 'block';
@@ -3833,7 +3844,8 @@ https://console.developers.google.com/apis/api/firestore.googleapis.com/overview
3833
3844
  return new Promise((resolve7, reject) => {
3834
3845
  const proc = (0, import_node_child_process2.execFile)(command, args, { cwd: cwd || this.projectDir, timeout: timeoutMs }, (err, stdout, stderr) => {
3835
3846
  if (err) {
3836
- const detail = stderr?.trim() || stdout?.trim() || "";
3847
+ const parts = [stderr?.trim(), stdout?.trim()].filter(Boolean);
3848
+ const detail = parts.join("\n");
3837
3849
  const enriched = new Error(`${err.message}${detail ? "\n" + detail : ""}`);
3838
3850
  reject(enriched);
3839
3851
  } else {
@@ -5062,45 +5074,38 @@ ${liveReloadScript}
5062
5074
  }
5063
5075
  steps.push("Hosting deployed");
5064
5076
  let blazeRequired = false;
5065
- let projectId = "";
5066
5077
  if (deployFunctions) {
5067
5078
  console.log(" Deploying functions...");
5068
5079
  const funcResult = await this.firebaseSetup.deployHosting("functions");
5069
5080
  if (funcResult.success) {
5070
- console.log(` \x1B[32m\u2713\x1B[0m Functions deployed`);
5081
+ console.log(" \x1B[32m\u2713\x1B[0m Functions deployed");
5071
5082
  steps.push("Functions deployed");
5072
5083
  } else {
5073
- const msg = funcResult.message.toLowerCase();
5074
- if (msg.includes("blaze") || msg.includes("pay-as-you-go") || msg.includes("upgrade") || msg.includes("billing") || msg.includes("artifactregistry")) {
5084
+ const errMsg = (funcResult.message || "").toLowerCase();
5085
+ const isBillingError = ["billing", "blaze", "pay-as-you-go", "upgrade your project", "budget"].some((kw) => errMsg.includes(kw));
5086
+ if (isBillingError) {
5075
5087
  blazeRequired = true;
5076
- const state = this.firebaseSetup.loadState();
5077
- projectId = state.projectId || firebaseConfig.projectId || "";
5078
- console.log(" \x1B[33m\u26A0\x1B[0m Functions require Blaze (pay-as-you-go) plan");
5088
+ console.log(" \x1B[33m\u26A0\x1B[0m Functions deploy failed (Blaze plan required)");
5079
5089
  steps.push("Functions skipped (Blaze plan required)");
5080
5090
  } else {
5081
5091
  console.log(` \x1B[31m\u2717\x1B[0m Functions deploy failed: ${funcResult.message}`);
5082
- steps.push("Functions deploy failed");
5092
+ steps.push(`Functions deploy failed: ${funcResult.message}`);
5083
5093
  }
5084
5094
  }
5085
5095
  }
5086
5096
  clearFirebaseStatusCache();
5097
+ const state = this.firebaseSetup.loadState();
5098
+ const projectId = state.projectId || firebaseConfig.projectId || "";
5099
+ const upgradeUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/usage/details` : "https://console.firebase.google.com";
5087
5100
  const stepsStr = steps.length > 0 ? ` (${steps.join(", ")})` : "";
5088
- if (blazeRequired) {
5089
- const upgradeUrl = projectId ? `https://console.firebase.google.com/project/${projectId}/usage/details` : "https://console.firebase.google.com";
5090
- sendJson({
5091
- success: true,
5092
- url: hostingResult.url,
5093
- blazeRequired: true,
5094
- upgradeUrl,
5095
- message: `Hosting deployed successfully!${stepsStr}`,
5096
- billingNote: `Static pages are live, but API routes (/api/*) require Cloud Functions which need the Blaze (pay-as-you-go) plan. Upgrade at: ${upgradeUrl}`
5097
- });
5098
- } else {
5099
- sendJson({
5100
- ...hostingResult,
5101
- message: hostingResult.message + stepsStr
5102
- });
5103
- }
5101
+ sendJson({
5102
+ success: true,
5103
+ url: hostingResult.url,
5104
+ blazeRequired,
5105
+ upgradeUrl: blazeRequired ? upgradeUrl : void 0,
5106
+ message: `Hosting deployed successfully!${stepsStr}`,
5107
+ billingNote: blazeRequired ? `Static pages are live! But API routes (/api/*) need Cloud Functions, which require the Blaze (pay-as-you-go) plan. Upgrade: ${upgradeUrl}` : void 0
5108
+ });
5104
5109
  } catch (err) {
5105
5110
  sendJson({ success: false, message: err instanceof Error ? err.message : "Failed" }, 500);
5106
5111
  }