clawfire 0.6.6 → 0.6.7
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/admin.cjs +1 -0
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +1 -0
- package/dist/admin.d.ts +1 -0
- package/dist/admin.js +1 -0
- package/dist/admin.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/{dev-server-PQP33VSE.js → dev-server-5SXODXYN.js} +185 -24
- package/dist/dev.cjs +166 -5
- package/dist/dev.cjs.map +1 -1
- package/dist/dev.js +185 -24
- package/dist/dev.js.map +1 -1
- package/dist/functions.cjs +1 -0
- package/dist/functions.cjs.map +1 -1
- package/dist/functions.js +1 -0
- package/dist/functions.js.map +1 -1
- package/dist/{hosting-7WVFHAYJ.js → hosting-GHMSBL2N.js} +1 -0
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/dev/dev-server.ts
|
|
2
2
|
import http from "http";
|
|
3
3
|
import { resolve as resolve6, relative as relative3, extname as extname3 } from "path";
|
|
4
|
-
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as
|
|
4
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
5
5
|
import { pathToFileURL } from "url";
|
|
6
6
|
|
|
7
7
|
// src/core/schema.ts
|
|
@@ -1019,8 +1019,8 @@ var FileWatcher = class extends EventEmitter {
|
|
|
1019
1019
|
};
|
|
1020
1020
|
|
|
1021
1021
|
// src/dev/page-compiler.ts
|
|
1022
|
-
import { resolve as resolve2, join as join3, dirname, basename } from "path";
|
|
1023
|
-
import { existsSync as existsSync3, readFileSync } from "fs";
|
|
1022
|
+
import { resolve as resolve2, join as join3, relative as relative2, dirname, basename } from "path";
|
|
1023
|
+
import { existsSync as existsSync3, readFileSync, readdirSync as readdirSync3, statSync as statSync3, writeFileSync, mkdirSync } from "fs";
|
|
1024
1024
|
var MAX_COMPONENT_DEPTH = 10;
|
|
1025
1025
|
var META_REGEX = /<!--\s*@(\w+):\s*(.+?)\s*-->/g;
|
|
1026
1026
|
var COMPONENT_REGEX = /<c-([a-z][a-z0-9-]*)\s*\/>/g;
|
|
@@ -1115,6 +1115,62 @@ var PageCompiler = class {
|
|
|
1115
1115
|
path: pathname
|
|
1116
1116
|
};
|
|
1117
1117
|
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Build all pages into static HTML for production deployment.
|
|
1120
|
+
* Walks app/pages/ recursively, compiles each page, and writes to outputDir.
|
|
1121
|
+
*
|
|
1122
|
+
* - Skips _layout.html (wrapper-only, not standalone)
|
|
1123
|
+
* - _404.html → 404.html (Firebase auto-serves for 404s)
|
|
1124
|
+
* - Injects optional script (e.g. production router) before </body>
|
|
1125
|
+
*/
|
|
1126
|
+
buildForProduction(outputDir, scriptToInject) {
|
|
1127
|
+
const pages = [];
|
|
1128
|
+
const errors = [];
|
|
1129
|
+
if (!this.isActive()) {
|
|
1130
|
+
return { pages, errors };
|
|
1131
|
+
}
|
|
1132
|
+
const walk = (dir) => {
|
|
1133
|
+
const entries = readdirSync3(dir);
|
|
1134
|
+
for (const entry of entries) {
|
|
1135
|
+
const fullPath = join3(dir, entry);
|
|
1136
|
+
const stat = statSync3(fullPath);
|
|
1137
|
+
if (stat.isDirectory()) {
|
|
1138
|
+
walk(fullPath);
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
if (!entry.endsWith(".html")) continue;
|
|
1142
|
+
if (entry === "_layout.html") continue;
|
|
1143
|
+
try {
|
|
1144
|
+
const compiled = this.compile(fullPath);
|
|
1145
|
+
let html = compiled.html;
|
|
1146
|
+
if (scriptToInject) {
|
|
1147
|
+
if (html.includes("</body>")) {
|
|
1148
|
+
html = html.replace("</body>", scriptToInject + "\n</body>");
|
|
1149
|
+
} else {
|
|
1150
|
+
html += scriptToInject;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
const relPath = relative2(this.pagesDir, fullPath);
|
|
1154
|
+
let outputPath;
|
|
1155
|
+
if (entry === "_404.html") {
|
|
1156
|
+
const parentRel = relative2(this.pagesDir, dir);
|
|
1157
|
+
outputPath = parentRel ? join3(outputDir, parentRel, "404.html") : join3(outputDir, "404.html");
|
|
1158
|
+
} else {
|
|
1159
|
+
outputPath = join3(outputDir, relPath);
|
|
1160
|
+
}
|
|
1161
|
+
const outputDirPath = dirname(outputPath);
|
|
1162
|
+
mkdirSync(outputDirPath, { recursive: true });
|
|
1163
|
+
writeFileSync(outputPath, html, "utf-8");
|
|
1164
|
+
pages.push(relPath);
|
|
1165
|
+
} catch (err) {
|
|
1166
|
+
const relPath = relative2(this.pagesDir, fullPath);
|
|
1167
|
+
errors.push(`${relPath}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
walk(this.pagesDir);
|
|
1172
|
+
return { pages, errors };
|
|
1173
|
+
}
|
|
1118
1174
|
// ─── Internal Methods ────────────────────────────────────────────
|
|
1119
1175
|
/**
|
|
1120
1176
|
* Extract <!-- @key: value --> metadata from HTML.
|
|
@@ -1193,7 +1249,7 @@ ${html}
|
|
|
1193
1249
|
};
|
|
1194
1250
|
|
|
1195
1251
|
// src/dev/env-manager.ts
|
|
1196
|
-
import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync4 } from "fs";
|
|
1252
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync4 } from "fs";
|
|
1197
1253
|
import { resolve as resolve3 } from "path";
|
|
1198
1254
|
var KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/i;
|
|
1199
1255
|
var PLACEHOLDER_PATTERNS = [
|
|
@@ -1267,7 +1323,7 @@ var EnvManager = class {
|
|
|
1267
1323
|
lines.push(`${key}=${value}`);
|
|
1268
1324
|
}
|
|
1269
1325
|
}
|
|
1270
|
-
|
|
1326
|
+
writeFileSync2(this.envPath, lines.join("\n"), "utf-8");
|
|
1271
1327
|
if (description !== void 0) {
|
|
1272
1328
|
const descriptions = this.readDescriptions();
|
|
1273
1329
|
descriptions[key] = description;
|
|
@@ -1285,7 +1341,7 @@ var EnvManager = class {
|
|
|
1285
1341
|
if (eqIdx === -1) return true;
|
|
1286
1342
|
return trimmed.slice(0, eqIdx).trim() !== key;
|
|
1287
1343
|
});
|
|
1288
|
-
|
|
1344
|
+
writeFileSync2(this.envPath, filtered.join("\n"), "utf-8");
|
|
1289
1345
|
const descriptions = this.readDescriptions();
|
|
1290
1346
|
if (key in descriptions) {
|
|
1291
1347
|
delete descriptions[key];
|
|
@@ -1302,7 +1358,7 @@ var EnvManager = class {
|
|
|
1302
1358
|
}
|
|
1303
1359
|
}
|
|
1304
1360
|
writeDescriptions(descriptions) {
|
|
1305
|
-
|
|
1361
|
+
writeFileSync2(
|
|
1306
1362
|
this.descriptionsPath,
|
|
1307
1363
|
JSON.stringify(descriptions, null, 2) + "\n",
|
|
1308
1364
|
"utf-8"
|
|
@@ -2955,7 +3011,7 @@ function generateDashboardHtml(options) {
|
|
|
2955
3011
|
|
|
2956
3012
|
// src/dev/firebase-setup.ts
|
|
2957
3013
|
import { execFile as execFile2, spawn } from "child_process";
|
|
2958
|
-
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as
|
|
3014
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
2959
3015
|
import { resolve as resolve5, join as join4 } from "path";
|
|
2960
3016
|
import { tmpdir, platform, homedir } from "os";
|
|
2961
3017
|
var FirebaseSetup = class {
|
|
@@ -2978,7 +3034,7 @@ var FirebaseSetup = class {
|
|
|
2978
3034
|
saveState(partial) {
|
|
2979
3035
|
const current = this.loadState();
|
|
2980
3036
|
const merged = { ...current, ...partial, lastUpdated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
2981
|
-
|
|
3037
|
+
writeFileSync3(this.stateFilePath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
2982
3038
|
}
|
|
2983
3039
|
// ─── Status Check ──────────────────────────────────────────────────
|
|
2984
3040
|
async getStatus() {
|
|
@@ -3080,7 +3136,7 @@ var FirebaseSetup = class {
|
|
|
3080
3136
|
try {
|
|
3081
3137
|
if (os === "darwin") {
|
|
3082
3138
|
const scriptPath = join4(tmpdir(), "clawfire-firebase-login.command");
|
|
3083
|
-
|
|
3139
|
+
writeFileSync3(scriptPath, [
|
|
3084
3140
|
"#!/bin/bash",
|
|
3085
3141
|
`cd "${this.projectDir}"`,
|
|
3086
3142
|
cmd,
|
|
@@ -3102,7 +3158,7 @@ var FirebaseSetup = class {
|
|
|
3102
3158
|
child.unref();
|
|
3103
3159
|
} else {
|
|
3104
3160
|
const scriptPath = join4(tmpdir(), "clawfire-firebase-login.sh");
|
|
3105
|
-
|
|
3161
|
+
writeFileSync3(scriptPath, [
|
|
3106
3162
|
"#!/bin/bash",
|
|
3107
3163
|
`cd "${this.projectDir}"`,
|
|
3108
3164
|
cmd,
|
|
@@ -3211,7 +3267,7 @@ var FirebaseSetup = class {
|
|
|
3211
3267
|
rc.projects = {};
|
|
3212
3268
|
}
|
|
3213
3269
|
rc.projects.default = projectId;
|
|
3214
|
-
|
|
3270
|
+
writeFileSync3(firebasercPath, JSON.stringify(rc, null, 2) + "\n", "utf-8");
|
|
3215
3271
|
return { success: true, message: `Active project set to "${projectId}".` };
|
|
3216
3272
|
} catch {
|
|
3217
3273
|
try {
|
|
@@ -3219,7 +3275,7 @@ var FirebaseSetup = class {
|
|
|
3219
3275
|
const rc = {
|
|
3220
3276
|
projects: { default: projectId }
|
|
3221
3277
|
};
|
|
3222
|
-
|
|
3278
|
+
writeFileSync3(firebasercPath, JSON.stringify(rc, null, 2) + "\n", "utf-8");
|
|
3223
3279
|
return { success: true, message: `Active project set to "${projectId}" (via .firebaserc).` };
|
|
3224
3280
|
} catch (writeErr) {
|
|
3225
3281
|
const msg = writeErr instanceof Error ? writeErr.message : "Unknown error";
|
|
@@ -3338,7 +3394,11 @@ var FirebaseSetup = class {
|
|
|
3338
3394
|
config.hosting = {
|
|
3339
3395
|
public: "public",
|
|
3340
3396
|
ignore: ["firebase.json", "**/.*", "**/node_modules/**"],
|
|
3341
|
-
|
|
3397
|
+
cleanUrls: true,
|
|
3398
|
+
rewrites: [
|
|
3399
|
+
{ source: "/api/**", function: "api" },
|
|
3400
|
+
{ source: "**", destination: "/index.html" }
|
|
3401
|
+
]
|
|
3342
3402
|
};
|
|
3343
3403
|
}
|
|
3344
3404
|
break;
|
|
@@ -3352,14 +3412,14 @@ var FirebaseSetup = class {
|
|
|
3352
3412
|
}
|
|
3353
3413
|
const rulesPath = resolve5(this.projectDir, "firestore.rules");
|
|
3354
3414
|
if (!existsSync6(rulesPath)) {
|
|
3355
|
-
|
|
3415
|
+
writeFileSync3(
|
|
3356
3416
|
rulesPath,
|
|
3357
3417
|
"rules_version = '2';\nservice cloud.firestore {\n match /databases/{database}/documents {\n match /{document=**} {\n allow read, write: if request.auth != null;\n }\n }\n}\n"
|
|
3358
3418
|
);
|
|
3359
3419
|
}
|
|
3360
3420
|
const indexesPath = resolve5(this.projectDir, "firestore.indexes.json");
|
|
3361
3421
|
if (!existsSync6(indexesPath)) {
|
|
3362
|
-
|
|
3422
|
+
writeFileSync3(indexesPath, JSON.stringify({ indexes: [], fieldOverrides: [] }, null, 2) + "\n");
|
|
3363
3423
|
}
|
|
3364
3424
|
break;
|
|
3365
3425
|
}
|
|
@@ -3369,7 +3429,7 @@ var FirebaseSetup = class {
|
|
|
3369
3429
|
}
|
|
3370
3430
|
const storageRulesPath = resolve5(this.projectDir, "storage.rules");
|
|
3371
3431
|
if (!existsSync6(storageRulesPath)) {
|
|
3372
|
-
|
|
3432
|
+
writeFileSync3(
|
|
3373
3433
|
storageRulesPath,
|
|
3374
3434
|
"rules_version = '2';\nservice firebase.storage {\n match /b/{bucket}/o {\n match /{allPaths=**} {\n allow read, write: if request.auth != null;\n }\n }\n}\n"
|
|
3375
3435
|
);
|
|
@@ -3377,7 +3437,7 @@ var FirebaseSetup = class {
|
|
|
3377
3437
|
break;
|
|
3378
3438
|
}
|
|
3379
3439
|
}
|
|
3380
|
-
|
|
3440
|
+
writeFileSync3(firebaseJsonPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3381
3441
|
return { success: true, message: `${service} enabled in firebase.json.` };
|
|
3382
3442
|
}
|
|
3383
3443
|
// ─── Firestore Database Automation ──────────────────────────────────
|
|
@@ -3548,7 +3608,7 @@ https://console.developers.google.com/apis/api/firestore.googleapis.com/overview
|
|
|
3548
3608
|
const rulesPath = resolve5(this.projectDir, "firestore.rules");
|
|
3549
3609
|
try {
|
|
3550
3610
|
if (openForDev) {
|
|
3551
|
-
|
|
3611
|
+
writeFileSync3(
|
|
3552
3612
|
rulesPath,
|
|
3553
3613
|
"rules_version = '2';\nservice cloud.firestore {\n match /databases/{database}/documents {\n match /{document=**} {\n allow read, write: if true;\n }\n }\n}\n"
|
|
3554
3614
|
);
|
|
@@ -3814,6 +3874,92 @@ function generateRouterScript() {
|
|
|
3814
3874
|
})();
|
|
3815
3875
|
</script>`;
|
|
3816
3876
|
}
|
|
3877
|
+
function generateProductionRouterScript() {
|
|
3878
|
+
return `
|
|
3879
|
+
<script data-clawfire-router>
|
|
3880
|
+
(function() {
|
|
3881
|
+
function updateActiveNav() {
|
|
3882
|
+
var path = location.pathname;
|
|
3883
|
+
var links = document.querySelectorAll('#nav-links a[href]');
|
|
3884
|
+
for (var i = 0; i < links.length; i++) {
|
|
3885
|
+
var href = links[i].getAttribute('href');
|
|
3886
|
+
if (!href || href.startsWith('http')) continue;
|
|
3887
|
+
var isActive = (path === '/' && href === '/') || (href !== '/' && path.startsWith(href));
|
|
3888
|
+
links[i].setAttribute('data-active', isActive ? 'true' : 'false');
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
|
|
3892
|
+
function navigate(url) {
|
|
3893
|
+
var target = new URL(url, location.href);
|
|
3894
|
+
if (target.origin !== location.origin) return false;
|
|
3895
|
+
if (target.pathname === location.pathname && target.hash) return false;
|
|
3896
|
+
|
|
3897
|
+
fetch(target.pathname)
|
|
3898
|
+
.then(function(res) {
|
|
3899
|
+
if (!res.ok) throw new Error('Page not found');
|
|
3900
|
+
return res.text();
|
|
3901
|
+
})
|
|
3902
|
+
.then(function(html) {
|
|
3903
|
+
// Parse the fetched full HTML and extract #clawfire-page content
|
|
3904
|
+
var parser = new DOMParser();
|
|
3905
|
+
var doc = parser.parseFromString(html, 'text/html');
|
|
3906
|
+
var newPage = doc.getElementById('clawfire-page');
|
|
3907
|
+
if (!newPage) throw new Error('No #clawfire-page found');
|
|
3908
|
+
|
|
3909
|
+
var container = document.getElementById('clawfire-page');
|
|
3910
|
+
if (container) {
|
|
3911
|
+
container.innerHTML = newPage.innerHTML;
|
|
3912
|
+
// Execute scripts in new content
|
|
3913
|
+
var scripts = container.querySelectorAll('script');
|
|
3914
|
+
for (var i = 0; i < scripts.length; i++) {
|
|
3915
|
+
var newScript = document.createElement('script');
|
|
3916
|
+
if (scripts[i].src) {
|
|
3917
|
+
newScript.src = scripts[i].src;
|
|
3918
|
+
} else {
|
|
3919
|
+
newScript.textContent = scripts[i].textContent;
|
|
3920
|
+
}
|
|
3921
|
+
scripts[i].parentNode.replaceChild(newScript, scripts[i]);
|
|
3922
|
+
}
|
|
3923
|
+
}
|
|
3924
|
+
// Update title from fetched document
|
|
3925
|
+
var newTitle = doc.querySelector('title');
|
|
3926
|
+
if (newTitle) document.title = newTitle.textContent || '';
|
|
3927
|
+
// Update URL
|
|
3928
|
+
history.pushState(null, '', target.pathname);
|
|
3929
|
+
updateActiveNav();
|
|
3930
|
+
document.dispatchEvent(new CustomEvent('clawfire:navigate', { detail: { path: target.pathname } }));
|
|
3931
|
+
window.scrollTo(0, 0);
|
|
3932
|
+
})
|
|
3933
|
+
.catch(function() {
|
|
3934
|
+
// Fallback: full page navigation
|
|
3935
|
+
location.href = url;
|
|
3936
|
+
});
|
|
3937
|
+
|
|
3938
|
+
return true;
|
|
3939
|
+
}
|
|
3940
|
+
|
|
3941
|
+
document.addEventListener('click', function(e) {
|
|
3942
|
+
var anchor = e.target.closest ? e.target.closest('a[href]') : null;
|
|
3943
|
+
if (!anchor) return;
|
|
3944
|
+
var href = anchor.getAttribute('href');
|
|
3945
|
+
if (!href) return;
|
|
3946
|
+
if (href.startsWith('http') || href.startsWith('//')) return;
|
|
3947
|
+
if (anchor.target === '_blank') return;
|
|
3948
|
+
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
|
|
3949
|
+
if (anchor.hasAttribute('download')) return;
|
|
3950
|
+
|
|
3951
|
+
e.preventDefault();
|
|
3952
|
+
navigate(href);
|
|
3953
|
+
});
|
|
3954
|
+
|
|
3955
|
+
window.addEventListener('popstate', function() {
|
|
3956
|
+
navigate(location.pathname);
|
|
3957
|
+
});
|
|
3958
|
+
|
|
3959
|
+
updateActiveNav();
|
|
3960
|
+
})();
|
|
3961
|
+
</script>`;
|
|
3962
|
+
}
|
|
3817
3963
|
var DevServer = class {
|
|
3818
3964
|
frontendServer = null;
|
|
3819
3965
|
apiServer = null;
|
|
@@ -4642,10 +4788,25 @@ ${liveReloadScript}
|
|
|
4642
4788
|
return;
|
|
4643
4789
|
}
|
|
4644
4790
|
if (url.pathname === "/__dev/deploy/hosting" && req.method === "POST") {
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4791
|
+
(async () => {
|
|
4792
|
+
try {
|
|
4793
|
+
if (this.pageCompiler.isActive()) {
|
|
4794
|
+
const routerScript = generateProductionRouterScript();
|
|
4795
|
+
const buildResult = this.pageCompiler.buildForProduction(this.publicDir, routerScript);
|
|
4796
|
+
console.log(` \x1B[32m\u2713\x1B[0m Built ${buildResult.pages.length} pages for production`);
|
|
4797
|
+
if (buildResult.errors.length > 0) {
|
|
4798
|
+
for (const err of buildResult.errors) {
|
|
4799
|
+
console.log(` \x1B[31m\u2717\x1B[0m ${err}`);
|
|
4800
|
+
}
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
const result = await this.firebaseSetup.deployHosting();
|
|
4804
|
+
clearFirebaseStatusCache();
|
|
4805
|
+
sendJson(result);
|
|
4806
|
+
} catch (err) {
|
|
4807
|
+
sendJson({ success: false, message: err instanceof Error ? err.message : "Failed" }, 500);
|
|
4808
|
+
}
|
|
4809
|
+
})();
|
|
4649
4810
|
return;
|
|
4650
4811
|
}
|
|
4651
4812
|
if (url.pathname === "/__dev/enable-service" && req.method === "POST") {
|
|
@@ -4792,7 +4953,7 @@ ${liveReloadScript}
|
|
|
4792
4953
|
throw new Error(`Key "${key}" not found in config`);
|
|
4793
4954
|
}
|
|
4794
4955
|
content = content.replace(pattern, `$1"${value.replace(/"/g, '\\"')}"`);
|
|
4795
|
-
|
|
4956
|
+
writeFileSync4(configPath, content, "utf-8");
|
|
4796
4957
|
}
|
|
4797
4958
|
escapeRegex(s) {
|
|
4798
4959
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|