bun-plugin-stx 0.2.66 → 0.2.69
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/{chunk-wv4bcqba.js → chunk-sm4gbwrd.js} +58 -9
- package/dist/serve.d.ts +14 -0
- package/dist/serve.js +494 -386
- package/package.json +3 -3
|
@@ -583,10 +583,11 @@ function getRouterScript() {
|
|
|
583
583
|
return `
|
|
584
584
|
;(function(){
|
|
585
585
|
'use strict';
|
|
586
|
-
|
|
586
|
+
var ROUTER_REV=3;
|
|
587
|
+
if(window.__stxRouter&&window.__stxRouter.__rev===ROUTER_REV)return;
|
|
587
588
|
|
|
588
589
|
// \u2500\u2500 Configuration \u2500\u2500
|
|
589
|
-
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false};
|
|
590
|
+
var defaults={container:'main',loadingClass:'stx-navigating',viewTransitions:true,cache:true,scrollToTop:true,prefetch:true,progress:true,progressColor:'#78dce8',progressHeight:'2px',interceptAllLinks:false,prefetchCacheMax:50};
|
|
590
591
|
var o=Object.assign({},defaults,window.__stxRouterConfig||{},window.STX_ROUTER_OPTIONS||{});
|
|
591
592
|
var containerSel=o.container;
|
|
592
593
|
var debug=!!o.debug;
|
|
@@ -646,6 +647,40 @@ function getRouterScript() {
|
|
|
646
647
|
var prefetching={};
|
|
647
648
|
var isNavigating=false;
|
|
648
649
|
|
|
650
|
+
// LRU bookkeeping for cache/layoutCache/layoutGroupCache. Pre-fix
|
|
651
|
+
// (stacksjs/stx#1719) these were plain objects with no eviction, so
|
|
652
|
+
// hover-prefetch on a sidebar of 200 internal links retained ~10MB
|
|
653
|
+
// of HTML strings for the page's lifetime. cacheOrder is a most-
|
|
654
|
+
// recently-used-last list of keys; setCache pushes new entries and
|
|
655
|
+
// evicts the oldest when length exceeds o.prefetchCacheMax (default
|
|
656
|
+
// 50). touchCache promotes a key on cache-hit. We use a plain array
|
|
657
|
+
// rather than a Map to keep the diff localized and the runtime
|
|
658
|
+
// hand-minified shape consistent.
|
|
659
|
+
var cacheOrder=[];
|
|
660
|
+
function setCache(key,html,layout,group){
|
|
661
|
+
if(!(key in cache))cacheOrder.push(key);
|
|
662
|
+
cache[key]=html;
|
|
663
|
+
layoutCache[key]=layout;
|
|
664
|
+
layoutGroupCache[key]=group;
|
|
665
|
+
while(cacheOrder.length>o.prefetchCacheMax){
|
|
666
|
+
var oldest=cacheOrder.shift();
|
|
667
|
+
delete cache[oldest];
|
|
668
|
+
delete layoutCache[oldest];
|
|
669
|
+
delete layoutGroupCache[oldest];
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
function touchCache(key){
|
|
673
|
+
var i=cacheOrder.indexOf(key);
|
|
674
|
+
if(i>=0){cacheOrder.splice(i,1);cacheOrder.push(key)}
|
|
675
|
+
}
|
|
676
|
+
function evictCache(key){
|
|
677
|
+
var i=cacheOrder.indexOf(key);
|
|
678
|
+
if(i>=0)cacheOrder.splice(i,1);
|
|
679
|
+
delete cache[key];
|
|
680
|
+
delete layoutCache[key];
|
|
681
|
+
delete layoutGroupCache[key];
|
|
682
|
+
}
|
|
683
|
+
|
|
649
684
|
// Extract top-level CSS blocks (rules AND @media blocks with nested braces).
|
|
650
685
|
// The old regex ([^{}]+{[^{}]*}) silently dropped @media blocks because
|
|
651
686
|
// it couldn't handle nested braces \u2014 causing responsive classes (lg:, md:)
|
|
@@ -713,6 +748,12 @@ function getRouterScript() {
|
|
|
713
748
|
var u=new URL(url,location.origin);
|
|
714
749
|
return u.pathname+u.search;
|
|
715
750
|
}
|
|
751
|
+
// Keep SPA fetches inside the active locale (/en/... when viewing English).
|
|
752
|
+
function withCurrentLocale(href){
|
|
753
|
+
var d=window.__stxI18n;
|
|
754
|
+
if(d&&typeof d.localizeHref==='function')return d.localizeHref(href);
|
|
755
|
+
return href;
|
|
756
|
+
}
|
|
716
757
|
function defaultLayoutGroup(layout){
|
|
717
758
|
if(!layout)return 'app';
|
|
718
759
|
var clean=String(layout).replace(/\\\\/g,'/');
|
|
@@ -756,6 +797,9 @@ function getRouterScript() {
|
|
|
756
797
|
}
|
|
757
798
|
|
|
758
799
|
function navigate(url,pushState,force){
|
|
800
|
+
// Lang-picker passes force=true with an already-localized path (/en/...).
|
|
801
|
+
// Re-localizing would map it back to the *current* locale and no-op.
|
|
802
|
+
if(!force) url=withCurrentLocale(url);
|
|
759
803
|
log('[router] navigate() called:',url,'isNavigating:',isNavigating);
|
|
760
804
|
if(isNavigating)return;
|
|
761
805
|
var t=new URL(url,location.origin);
|
|
@@ -788,6 +832,9 @@ function getRouterScript() {
|
|
|
788
832
|
function done(){isNavigating=false;document.body.classList.remove(o.loadingClass);finishProgress()}
|
|
789
833
|
|
|
790
834
|
if(o.cache&&cache[targetPath]&&!force){
|
|
835
|
+
// Cache hit \u2192 promote in LRU order so this entry survives eviction
|
|
836
|
+
// longer than other entries that haven't been touched.
|
|
837
|
+
touchCache(targetPath);
|
|
791
838
|
if(checkLayoutChange(layoutCache[targetPath],url,layoutGroupCache[targetPath])){
|
|
792
839
|
// Layout changed \u2014 fetch full page and do full document swap
|
|
793
840
|
log('[router] cache hit but layout changed \u2014 fetching full page');
|
|
@@ -807,7 +854,7 @@ function getRouterScript() {
|
|
|
807
854
|
done();
|
|
808
855
|
}
|
|
809
856
|
else {
|
|
810
|
-
if(force&&cache[targetPath])
|
|
857
|
+
if(force&&cache[targetPath])evictCache(targetPath);
|
|
811
858
|
// First fetch as fragment (SPA mode) when the configured container is
|
|
812
859
|
// the page content. Custom app-shell containers need full documents so
|
|
813
860
|
// the router does not inject a <main> fragment into the wrong element.
|
|
@@ -833,7 +880,7 @@ else {
|
|
|
833
880
|
}).then(function(result){
|
|
834
881
|
if(!result)return;
|
|
835
882
|
if(result.isFragment)result.html='<!--stx-fragment-->'+result.html;
|
|
836
|
-
if(o.cache)
|
|
883
|
+
if(o.cache)setCache(targetPath,result.html,result.layout,result.layoutGroup);
|
|
837
884
|
swap(result.html,targetPath,pushState,targetHash);
|
|
838
885
|
}).catch(function(err){
|
|
839
886
|
console.error('[router] fetch error:',err);
|
|
@@ -1207,6 +1254,7 @@ else {
|
|
|
1207
1254
|
if(href.startsWith('http')||href.startsWith('#')||href.startsWith('mailto:')||href.startsWith('tel:')||href.startsWith('javascript:'))return false;
|
|
1208
1255
|
if(link.target==='_blank')return false;
|
|
1209
1256
|
if(link.hasAttribute('data-stx-no-router')||link.hasAttribute('data-no-router')||link.hasAttribute('download'))return false;
|
|
1257
|
+
if(href.startsWith('?'))return true;
|
|
1210
1258
|
if(href===location.pathname)return false;
|
|
1211
1259
|
if(!getContainer())return false;
|
|
1212
1260
|
return true;
|
|
@@ -1233,7 +1281,7 @@ else {
|
|
|
1233
1281
|
e.preventDefault();
|
|
1234
1282
|
e.stopPropagation();
|
|
1235
1283
|
log('[router] navigating to:',href);
|
|
1236
|
-
navigate(href);
|
|
1284
|
+
navigate(withCurrentLocale(href));
|
|
1237
1285
|
},true);
|
|
1238
1286
|
|
|
1239
1287
|
// \u2500\u2500 Back/forward \u2500\u2500
|
|
@@ -1247,7 +1295,7 @@ else {
|
|
|
1247
1295
|
if(!e.target||!e.target.closest)return;
|
|
1248
1296
|
var link=e.target.closest('[data-stx-link]');
|
|
1249
1297
|
if(!link)return;
|
|
1250
|
-
var href=link.getAttribute('href');
|
|
1298
|
+
var href=withCurrentLocale(link.getAttribute('href'));
|
|
1251
1299
|
var key=cacheKey(href);
|
|
1252
1300
|
if(cache[key]||prefetching[key])return;
|
|
1253
1301
|
prefetching[key]=true;
|
|
@@ -1258,7 +1306,7 @@ else {
|
|
|
1258
1306
|
var pGroup=r.headers.get('X-STX-Layout-Group')||'';
|
|
1259
1307
|
return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}});
|
|
1260
1308
|
}).then(function(result){
|
|
1261
|
-
if(o.cache)
|
|
1309
|
+
if(o.cache)setCache(key,result.html,result.layout,result.layoutGroup);
|
|
1262
1310
|
}).catch(function(){}).finally(function(){delete prefetching[key]});
|
|
1263
1311
|
},true);
|
|
1264
1312
|
}
|
|
@@ -1355,15 +1403,16 @@ else {
|
|
|
1355
1403
|
var key=cacheKey(url);
|
|
1356
1404
|
if(!cache[key]){
|
|
1357
1405
|
var wantsFragment=shouldUseFragmentResponse();
|
|
1358
|
-
fetch(url,{headers:wantsFragment?{'X-STX-Router':'true'}:{'Accept':'text/html'}}).then(function(r){var isFrag=wantsFragment&&r.headers.get('X-STX-Fragment')==='true';var pLayout=r.headers.get('X-STX-Layout')||'';var pGroup=r.headers.get('X-STX-Layout-Group')||'';return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}})}).then(function(result){
|
|
1406
|
+
fetch(url,{headers:wantsFragment?{'X-STX-Router':'true'}:{'Accept':'text/html'}}).then(function(r){var isFrag=wantsFragment&&r.headers.get('X-STX-Fragment')==='true';var pLayout=r.headers.get('X-STX-Layout')||'';var pGroup=r.headers.get('X-STX-Layout-Group')||'';return r.text().then(function(html){return{html:isFrag?'<!--stx-fragment-->'+html:html,layout:pLayout,layoutGroup:pGroup}})}).then(function(result){setCache(key,result.html,result.layout,result.layoutGroup)}).catch(function(){});
|
|
1359
1407
|
}
|
|
1360
1408
|
},
|
|
1361
|
-
clearCache:function(){for(var k in cache)delete cache[k];for(var lk in layoutCache)delete layoutCache[lk];for(var gk in layoutGroupCache)delete layoutGroupCache[gk]},
|
|
1409
|
+
clearCache:function(){for(var k in cache)delete cache[k];for(var lk in layoutCache)delete layoutCache[lk];for(var gk in layoutGroupCache)delete layoutGroupCache[gk];cacheOrder.length=0},
|
|
1362
1410
|
cache:cache,
|
|
1363
1411
|
swap:swap,
|
|
1364
1412
|
updateNav:updateNav
|
|
1365
1413
|
};
|
|
1366
1414
|
|
|
1415
|
+
router.__rev=ROUTER_REV;
|
|
1367
1416
|
window.__stxRouter=router;
|
|
1368
1417
|
window.stxRouter=router;
|
|
1369
1418
|
if(window.stx)window.stx.router=router;
|
package/dist/serve.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the candidate regexes for a dynamic route file (stacksjs/stx#1927).
|
|
3
|
+
*
|
|
4
|
+
* `fileRouteBase` is the route path with the file extension already
|
|
5
|
+
* stripped (e.g. `judges/[id]/profile/index`). Returns one regex per
|
|
6
|
+
* acceptable URL shape:
|
|
7
|
+
* - the literal path with `[param]` → `([^/]+)`
|
|
8
|
+
* - the same with a trailing `/index` removed, so
|
|
9
|
+
* `judges/[id]/profile/index` also matches `judges/35/profile`
|
|
10
|
+
* (without this, nested dynamic routes 404 on hard reload)
|
|
11
|
+
* - both of the above again with a leading `pages/` stripped, for
|
|
12
|
+
* projects that nest routable views under `pages/`
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildDynamicRouteRegexes(fileRouteBase: string): RegExp[];
|
|
1
15
|
export declare function bundleBrowserAsset(entrypoint: string): Promise<Response>;
|
|
2
16
|
/**
|
|
3
17
|
* Start the STX development server
|
package/dist/serve.js
CHANGED
|
@@ -7039,6 +7039,7 @@ class Logger3 {
|
|
|
7039
7039
|
}
|
|
7040
7040
|
}
|
|
7041
7041
|
var logger3 = new Logger3("stacks");
|
|
7042
|
+
|
|
7042
7043
|
class BunfigError2 extends Error {
|
|
7043
7044
|
timestamp;
|
|
7044
7045
|
context;
|
|
@@ -8693,6 +8694,21 @@ var defaultGeneratedDir4 = resolve12(process20.cwd(), "src/generated");
|
|
|
8693
8694
|
|
|
8694
8695
|
// src/serve.ts
|
|
8695
8696
|
var defaultStxModule = import("@stacksjs/stx");
|
|
8697
|
+
function buildDynamicRouteRegexes(fileRouteBase) {
|
|
8698
|
+
const toPattern = (p) => p.replace(/\[([^\]]+)\]/g, "([^/]+)").replace(/\//g, "\\/");
|
|
8699
|
+
const patterns = [new RegExp(`^${toPattern(fileRouteBase)}$`)];
|
|
8700
|
+
const noIndex = fileRouteBase.replace(/\/index$/, "");
|
|
8701
|
+
if (noIndex !== fileRouteBase)
|
|
8702
|
+
patterns.push(new RegExp(`^${toPattern(noIndex)}$`));
|
|
8703
|
+
if (fileRouteBase.startsWith("pages/")) {
|
|
8704
|
+
const pretty = fileRouteBase.slice(6);
|
|
8705
|
+
patterns.push(new RegExp(`^${toPattern(pretty)}$`));
|
|
8706
|
+
const prettyNoIndex = pretty.replace(/\/index$/, "");
|
|
8707
|
+
if (prettyNoIndex !== pretty)
|
|
8708
|
+
patterns.push(new RegExp(`^${toPattern(prettyNoIndex)}$`));
|
|
8709
|
+
}
|
|
8710
|
+
return patterns;
|
|
8711
|
+
}
|
|
8696
8712
|
var defaultStxConfig = {
|
|
8697
8713
|
partialsDir: "partials",
|
|
8698
8714
|
componentsDir: "components",
|
|
@@ -8766,22 +8782,25 @@ async function bundleBrowserAsset(entrypoint) {
|
|
|
8766
8782
|
status: 500,
|
|
8767
8783
|
headers: {
|
|
8768
8784
|
"Content-Type": "text/plain; charset=utf-8",
|
|
8769
|
-
"Cache-Control": "no-
|
|
8785
|
+
"Cache-Control": "no-store"
|
|
8770
8786
|
}
|
|
8771
8787
|
});
|
|
8772
8788
|
}
|
|
8773
8789
|
return new Response(await result.outputs[0].text(), {
|
|
8774
8790
|
headers: {
|
|
8775
8791
|
"Content-Type": "application/javascript",
|
|
8776
|
-
"Cache-Control": "no-
|
|
8792
|
+
"Cache-Control": "no-store"
|
|
8777
8793
|
}
|
|
8778
8794
|
});
|
|
8779
8795
|
}
|
|
8780
8796
|
async function serve(options) {
|
|
8781
8797
|
const stxConfig = await loadConfig6({
|
|
8782
8798
|
name: "stx",
|
|
8799
|
+
alias: ["ui"],
|
|
8783
8800
|
cwd: process19.cwd(),
|
|
8784
|
-
defaultConfig: defaultStxConfig
|
|
8801
|
+
defaultConfig: defaultStxConfig,
|
|
8802
|
+
checkEnv: false,
|
|
8803
|
+
verbose: false
|
|
8785
8804
|
});
|
|
8786
8805
|
try {
|
|
8787
8806
|
const stxMod = options.stxModule ? options.stxModule : await defaultStxModule;
|
|
@@ -8816,8 +8835,10 @@ After installing: bun add bun-plugin-stx`);
|
|
|
8816
8835
|
}
|
|
8817
8836
|
const routes = new Map;
|
|
8818
8837
|
let sourceFiles = null;
|
|
8838
|
+
let discoveredPagePaths = null;
|
|
8819
8839
|
let assetsInitialized = false;
|
|
8820
8840
|
const htmlCache = new Map;
|
|
8841
|
+
const ENABLE_HTML_CACHE = false;
|
|
8821
8842
|
const crosswindCssCache = new Map;
|
|
8822
8843
|
const hmrClients = new Set;
|
|
8823
8844
|
const hmrEncoder = new TextEncoder;
|
|
@@ -8988,6 +9009,31 @@ After installing: bun add bun-plugin-stx`);
|
|
|
8988
9009
|
const authRedirectTo = authConfig?.redirectTo ?? "/login";
|
|
8989
9010
|
const authHome = authConfig?.home ?? "/";
|
|
8990
9011
|
const extraProtectedPrefixes = authConfig?.protectedPaths ?? [];
|
|
9012
|
+
let activeServeLocale = null;
|
|
9013
|
+
let activeServeSearch = "";
|
|
9014
|
+
function injectServeLocaleContext(context) {
|
|
9015
|
+
if (!activeServeLocale)
|
|
9016
|
+
return;
|
|
9017
|
+
const loc = activeServeLocale;
|
|
9018
|
+
context.locale = loc;
|
|
9019
|
+
context.t = (key, values) => {
|
|
9020
|
+
const translate = globalThis.t;
|
|
9021
|
+
return typeof translate === "function" ? translate(key, values, loc) : key;
|
|
9022
|
+
};
|
|
9023
|
+
}
|
|
9024
|
+
function injectServeRequestContext(context) {
|
|
9025
|
+
if (!activeServeSearch)
|
|
9026
|
+
return;
|
|
9027
|
+
context.__stxServeSearch = activeServeSearch;
|
|
9028
|
+
globalThis.__stxServeSearch = activeServeSearch;
|
|
9029
|
+
}
|
|
9030
|
+
function htmlCacheKey(filePath) {
|
|
9031
|
+
const loc = i18nConfig ? activeServeLocale ?? i18nConfig.defaultLocale : "";
|
|
9032
|
+
const search = activeServeSearch || "";
|
|
9033
|
+
if (!loc && !search)
|
|
9034
|
+
return filePath;
|
|
9035
|
+
return `${filePath}\x00${loc}\x00${search}`;
|
|
9036
|
+
}
|
|
8991
9037
|
const builtInMiddleware = authConfig === null ? {} : {
|
|
8992
9038
|
auth: (_req, ctx) => {
|
|
8993
9039
|
const tok = ctx.cookies[authCookieName];
|
|
@@ -9024,6 +9070,37 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9024
9070
|
return out;
|
|
9025
9071
|
}
|
|
9026
9072
|
const globalMiddlewareNames = options.globalMiddleware ?? [];
|
|
9073
|
+
function stxViewFileToRoutePath(filePath) {
|
|
9074
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
9075
|
+
for (const pattern of patterns) {
|
|
9076
|
+
const normPattern = pattern.replace(/\\/g, "/").replace(/\/$/, "");
|
|
9077
|
+
if (!normalized.startsWith(`${normPattern}/`))
|
|
9078
|
+
continue;
|
|
9079
|
+
let rel = normalized.slice(normPattern.length + 1).replace(/\.(stx|md|html)$/, "");
|
|
9080
|
+
if (rel.includes("["))
|
|
9081
|
+
return null;
|
|
9082
|
+
if (rel === "index" || rel === "")
|
|
9083
|
+
return "/";
|
|
9084
|
+
if (rel.endsWith("/index"))
|
|
9085
|
+
rel = rel.slice(0, -6) || "index";
|
|
9086
|
+
return rel === "index" ? "/" : `/${rel}`;
|
|
9087
|
+
}
|
|
9088
|
+
return null;
|
|
9089
|
+
}
|
|
9090
|
+
function rebuildDiscoveredPagePaths(files) {
|
|
9091
|
+
const known = new Set(["/"]);
|
|
9092
|
+
for (const filePath of files) {
|
|
9093
|
+
const routePath = stxViewFileToRoutePath(filePath);
|
|
9094
|
+
if (routePath)
|
|
9095
|
+
known.add(routePath);
|
|
9096
|
+
}
|
|
9097
|
+
const pages = options.site?.pages;
|
|
9098
|
+
if (pages) {
|
|
9099
|
+
for (const p of Object.keys(pages))
|
|
9100
|
+
known.add(p.startsWith("/") ? p : `/${p}`);
|
|
9101
|
+
}
|
|
9102
|
+
discoveredPagePaths = known;
|
|
9103
|
+
}
|
|
9027
9104
|
async function discoverFiles() {
|
|
9028
9105
|
if (sourceFiles !== null)
|
|
9029
9106
|
return sourceFiles;
|
|
@@ -9059,14 +9136,16 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9059
9136
|
}
|
|
9060
9137
|
}
|
|
9061
9138
|
sourceFiles = files;
|
|
9139
|
+
rebuildDiscoveredPagePaths(files);
|
|
9062
9140
|
pageMiddlewareByPath.clear();
|
|
9063
9141
|
pageMiddlewarePatterns.length = 0;
|
|
9064
9142
|
await Promise.all(files.map((f) => detectPageMiddleware(f)));
|
|
9065
9143
|
try {
|
|
9066
|
-
const { Router } = await import("./chunk-
|
|
9144
|
+
const { Router } = await import("./chunk-sm4gbwrd.js");
|
|
9067
9145
|
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
9068
9146
|
const router = new Router(process19.cwd(), { pagesDirs });
|
|
9069
|
-
|
|
9147
|
+
if (!options.quiet)
|
|
9148
|
+
console.log(`[stx] Generated ${router.routes.length} routes \u2192 .stx/routes.ts`);
|
|
9070
9149
|
} catch (e) {}
|
|
9071
9150
|
return files;
|
|
9072
9151
|
}
|
|
@@ -9161,7 +9240,9 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9161
9240
|
crosswindUserConfigPromise = loadConfig6({
|
|
9162
9241
|
name: "crosswind",
|
|
9163
9242
|
cwd: process19.cwd(),
|
|
9164
|
-
defaultConfig: {}
|
|
9243
|
+
defaultConfig: {},
|
|
9244
|
+
checkEnv: false,
|
|
9245
|
+
verbose: false
|
|
9165
9246
|
});
|
|
9166
9247
|
}
|
|
9167
9248
|
const userConfig = await crosswindUserConfigPromise;
|
|
@@ -9229,10 +9310,14 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9229
9310
|
}
|
|
9230
9311
|
}
|
|
9231
9312
|
async function processTemplate(filePath) {
|
|
9232
|
-
const cachedEntry = htmlCache.get(filePath);
|
|
9233
|
-
if (cachedEntry && await templateSignatureFresh(cachedEntry.signature))
|
|
9234
|
-
return cachedEntry.html;
|
|
9235
9313
|
const content = await Bun.file(filePath).text();
|
|
9314
|
+
const skipCacheHint = /(?:^|[^\w$])__stx_skip_cache\s*=\s*true/.test(content);
|
|
9315
|
+
if (ENABLE_HTML_CACHE && !skipCacheHint) {
|
|
9316
|
+
const cacheKey = htmlCacheKey(filePath);
|
|
9317
|
+
const cachedEntry = htmlCache.get(cacheKey);
|
|
9318
|
+
if (cachedEntry && await templateSignatureFresh(cachedEntry.signature))
|
|
9319
|
+
return cachedEntry.html;
|
|
9320
|
+
}
|
|
9236
9321
|
const serverScriptRegex = /<script\b([^>]*)\bserver\b[^>]*>([\s\S]*?)<\/script>/gi;
|
|
9237
9322
|
const serverScripts = [];
|
|
9238
9323
|
let scriptMatch;
|
|
@@ -9246,6 +9331,8 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9246
9331
|
};
|
|
9247
9332
|
const { processDirectives, extractVariables, defaultConfig: defaultConfig4, generateSpaShell, injectRouterScript, resetHead } = await stxModule;
|
|
9248
9333
|
resetHead();
|
|
9334
|
+
injectServeLocaleContext(context);
|
|
9335
|
+
injectServeRequestContext(context);
|
|
9249
9336
|
for (const scriptBody of serverScripts) {
|
|
9250
9337
|
await extractVariables(scriptBody, context, filePath);
|
|
9251
9338
|
}
|
|
@@ -9278,7 +9365,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9278
9365
|
let output = templateContent;
|
|
9279
9366
|
const dependencies = new Set;
|
|
9280
9367
|
output = await processDirectives(output, context, filePath, config5, dependencies);
|
|
9281
|
-
output = await injectRouterScript(output);
|
|
9368
|
+
output = await injectRouterScript(output, getRouterInjectOptions());
|
|
9282
9369
|
const directiveTemplateRe = /@for|:for|@if|:if|x-for|x-if/;
|
|
9283
9370
|
const hasDirectiveTemplates = /<template\s[^>]*(?:@for|:for|@if|:if|x-for|x-if)/.test(output);
|
|
9284
9371
|
if (hasDirectiveTemplates) {
|
|
@@ -9292,9 +9379,9 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9292
9379
|
} else {
|
|
9293
9380
|
output = output.replace(/<template[^>]*>/gi, "").replace(/<\/template>/gi, "");
|
|
9294
9381
|
}
|
|
9295
|
-
if (!context.__stx_skip_cache) {
|
|
9382
|
+
if (ENABLE_HTML_CACHE && !context.__stx_skip_cache && !skipCacheHint) {
|
|
9296
9383
|
const signature = await buildTemplateSignature(filePath, dependencies);
|
|
9297
|
-
htmlCache.set(filePath, { html: output, signature });
|
|
9384
|
+
htmlCache.set(htmlCacheKey(filePath), { html: output, signature });
|
|
9298
9385
|
}
|
|
9299
9386
|
return output;
|
|
9300
9387
|
}
|
|
@@ -9378,25 +9465,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9378
9465
|
}
|
|
9379
9466
|
}
|
|
9380
9467
|
const fileRouteBase = relativeFilePath.replace(/\.(stx|md|html)$/, "");
|
|
9381
|
-
const
|
|
9382
|
-
const regexPatterns = [
|
|
9383
|
-
new RegExp(`^${routePattern}$`)
|
|
9384
|
-
];
|
|
9385
|
-
const fileRouteNoIndex = fileRouteBase.replace(/\/index$/, "");
|
|
9386
|
-
if (fileRouteNoIndex !== fileRouteBase) {
|
|
9387
|
-
const noIndexPattern = fileRouteNoIndex.replace(/\[([^\]]+)\]/g, "([^/]+)").replace(/\//g, "\\/");
|
|
9388
|
-
regexPatterns.push(new RegExp(`^${noIndexPattern}$`));
|
|
9389
|
-
}
|
|
9390
|
-
if (fileRouteBase.startsWith("pages/")) {
|
|
9391
|
-
const prettyBase = fileRouteBase.slice(6);
|
|
9392
|
-
const prettyPattern = prettyBase.replace(/\[([^\]]+)\]/g, "([^/]+)").replace(/\//g, "\\/");
|
|
9393
|
-
regexPatterns.push(new RegExp(`^${prettyPattern}$`));
|
|
9394
|
-
const prettyNoIndex = prettyBase.replace(/\/index$/, "");
|
|
9395
|
-
if (prettyNoIndex !== prettyBase) {
|
|
9396
|
-
const prettyNoIndexPattern = prettyNoIndex.replace(/\[([^\]]+)\]/g, "([^/]+)").replace(/\//g, "\\/");
|
|
9397
|
-
regexPatterns.push(new RegExp(`^${prettyNoIndexPattern}$`));
|
|
9398
|
-
}
|
|
9399
|
-
}
|
|
9468
|
+
const regexPatterns = buildDynamicRouteRegexes(fileRouteBase);
|
|
9400
9469
|
for (const regex of regexPatterns) {
|
|
9401
9470
|
const match = normalizedPath.match(regex);
|
|
9402
9471
|
if (match) {
|
|
@@ -9429,6 +9498,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9429
9498
|
}
|
|
9430
9499
|
const { processDirectives, extractVariables, defaultConfig: defaultConfig4, injectRouterScript: injectRouter, resetHead: resetHeadDyn } = await stxModule;
|
|
9431
9500
|
resetHeadDyn();
|
|
9501
|
+
injectServeLocaleContext(context);
|
|
9432
9502
|
for (const scriptBody of dynServerScripts) {
|
|
9433
9503
|
await extractVariables(scriptBody, context, filePath);
|
|
9434
9504
|
}
|
|
@@ -9468,7 +9538,7 @@ After installing: bun add bun-plugin-stx`);
|
|
|
9468
9538
|
${output}`;
|
|
9469
9539
|
}
|
|
9470
9540
|
}
|
|
9471
|
-
output = await injectRouter(output);
|
|
9541
|
+
output = await injectRouter(output, getRouterInjectOptions());
|
|
9472
9542
|
const directiveTemplateRe2 = /@for|:for|@if|:if|x-for|x-if/;
|
|
9473
9543
|
output = output.replace(/<template(?:\s[^>]*)?>|<\/template>/gi, (match) => {
|
|
9474
9544
|
if (directiveTemplateRe2.test(match))
|
|
@@ -9506,6 +9576,28 @@ ${output}`;
|
|
|
9506
9576
|
}
|
|
9507
9577
|
return { locale: i18nConfig.defaultLocale, path: pathname };
|
|
9508
9578
|
}
|
|
9579
|
+
function getRouterInjectOptions() {
|
|
9580
|
+
return {
|
|
9581
|
+
router: {
|
|
9582
|
+
interceptAllLinks: true,
|
|
9583
|
+
container: "main",
|
|
9584
|
+
...siteConfig?.router ?? {},
|
|
9585
|
+
...stxConfig.router ?? {}
|
|
9586
|
+
}
|
|
9587
|
+
};
|
|
9588
|
+
}
|
|
9589
|
+
function ensureRouterConfig(html) {
|
|
9590
|
+
const routerOpts = getRouterInjectOptions().router;
|
|
9591
|
+
const block = `<script>window.__stxRouterConfig=${JSON.stringify(routerOpts)};</script>
|
|
9592
|
+
`;
|
|
9593
|
+
const configTagRe = /<script>window\.__stxRouterConfig=\{[^<]*\}<\/script>\s*/i;
|
|
9594
|
+
if (configTagRe.test(html))
|
|
9595
|
+
return html.replace(configTagRe, block);
|
|
9596
|
+
if (/<\/body>/i.test(html))
|
|
9597
|
+
return html.replace(/<\/body>/i, `${block}</body>`);
|
|
9598
|
+
return `${html}
|
|
9599
|
+
${block}`;
|
|
9600
|
+
}
|
|
9509
9601
|
async function applyI18nToResponse(res, locale, normalizedPath) {
|
|
9510
9602
|
if (!siteStxPromise)
|
|
9511
9603
|
return res;
|
|
@@ -9536,8 +9628,8 @@ ${output}`;
|
|
|
9536
9628
|
html = `${groupMeta}
|
|
9537
9629
|
${html}`;
|
|
9538
9630
|
}
|
|
9539
|
-
|
|
9540
|
-
|
|
9631
|
+
const knownPaths = discoveredPagePaths ?? new Set;
|
|
9632
|
+
if (i18nConfig && locale !== i18nConfig.defaultLocale && knownPaths.size > 0) {
|
|
9541
9633
|
html = html.replace(/<a\b([^>]*?)\bhref="(\/[^"]*)"([^>]*)>/gi, (full, before, href, after) => {
|
|
9542
9634
|
if (href.startsWith("//"))
|
|
9543
9635
|
return full;
|
|
@@ -9556,6 +9648,7 @@ ${html}`;
|
|
|
9556
9648
|
}
|
|
9557
9649
|
if (i18nConfig && stx.applyTranslations)
|
|
9558
9650
|
html = stx.applyTranslations(html, i18nConfig, locale);
|
|
9651
|
+
html = ensureRouterConfig(html);
|
|
9559
9652
|
const headers = new Headers(res.headers);
|
|
9560
9653
|
headers.delete("content-length");
|
|
9561
9654
|
return new Response(html, {
|
|
@@ -9584,411 +9677,421 @@ ${html}`;
|
|
|
9584
9677
|
if (stripped.path !== url.pathname) {
|
|
9585
9678
|
const rewritten = new URL(req.url);
|
|
9586
9679
|
rewritten.pathname = stripped.path;
|
|
9587
|
-
|
|
9680
|
+
const headers = new Headers(req.headers);
|
|
9681
|
+
headers.set("x-stx-locale", stripped.locale);
|
|
9682
|
+
req = new Request(rewritten, { headers, method: req.method, body: req.body, redirect: req.redirect, duplex: "half" });
|
|
9588
9683
|
path = stripped.path;
|
|
9684
|
+
} else if (i18nLocale) {
|
|
9685
|
+
const headers = new Headers(req.headers);
|
|
9686
|
+
headers.set("x-stx-locale", i18nLocale);
|
|
9687
|
+
req = new Request(req, { headers });
|
|
9589
9688
|
}
|
|
9590
9689
|
}
|
|
9591
9690
|
const _i18nResp = await (async () => {
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
c
|
|
9691
|
+
activeServeLocale = i18nLocale;
|
|
9692
|
+
activeServeSearch = url.search;
|
|
9693
|
+
try {
|
|
9694
|
+
if (req.method === "OPTIONS") {
|
|
9695
|
+
return new Response(null, { headers: corsHeaders });
|
|
9696
|
+
}
|
|
9697
|
+
if (path === "/_stx/hmr") {
|
|
9698
|
+
let controller;
|
|
9699
|
+
let keepalive;
|
|
9700
|
+
const stream = new ReadableStream({
|
|
9701
|
+
start(c) {
|
|
9702
|
+
controller = c;
|
|
9703
|
+
hmrClients.add(c);
|
|
9704
|
+
c.enqueue(hmrEncoder.encode(`data: {"type":"connected"}
|
|
9603
9705
|
|
|
9604
9706
|
`));
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9707
|
+
keepalive = setInterval(() => {
|
|
9708
|
+
try {
|
|
9709
|
+
c.enqueue(hmrEncoder.encode(`: keepalive
|
|
9608
9710
|
|
|
9609
9711
|
`));
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9619
|
-
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
|
|
9627
|
-
|
|
9628
|
-
}
|
|
9629
|
-
if (options.onRequest) {
|
|
9630
|
-
const customResponse = await options.onRequest(req);
|
|
9631
|
-
if (customResponse)
|
|
9632
|
-
return customResponse;
|
|
9633
|
-
}
|
|
9634
|
-
const route = resolveRouteMiddleware(path);
|
|
9635
|
-
const extraNames = extraProtectedPrefixes.some((p) => path === p || path.startsWith(p.endsWith("/") ? p : `${p}/`)) ? ["auth"] : [];
|
|
9636
|
-
const requested = [...globalMiddlewareNames, ...route.names, ...extraNames];
|
|
9637
|
-
if (requested.length > 0) {
|
|
9638
|
-
const expanded = expandMiddlewareNames(requested);
|
|
9639
|
-
const cookies = parseCookies(req);
|
|
9640
|
-
const ctx = {
|
|
9641
|
-
path,
|
|
9642
|
-
url,
|
|
9643
|
-
params: route.params,
|
|
9644
|
-
cookies,
|
|
9645
|
-
redirect: (to, status = 302) => {
|
|
9646
|
-
const sep = to.includes("?") ? "&" : "?";
|
|
9647
|
-
const next = encodeURIComponent(path + (url.search || ""));
|
|
9648
|
-
return new Response(null, {
|
|
9649
|
-
status,
|
|
9650
|
-
headers: { Location: `${to}${sep}next=${next}` }
|
|
9651
|
-
});
|
|
9652
|
-
}
|
|
9653
|
-
};
|
|
9654
|
-
for (const entry of expanded) {
|
|
9655
|
-
const colon = entry.indexOf(":");
|
|
9656
|
-
const name = colon === -1 ? entry : entry.slice(0, colon);
|
|
9657
|
-
const args = colon === -1 ? [] : entry.slice(colon + 1).split(",");
|
|
9658
|
-
const handler = middlewareRegistry[name];
|
|
9659
|
-
if (!handler) {
|
|
9660
|
-
console.warn(`[stx serve] unknown middleware "${name}" on ${path}`);
|
|
9661
|
-
continue;
|
|
9662
|
-
}
|
|
9663
|
-
const result = await handler(req, ctx, ...args);
|
|
9664
|
-
if (result instanceof Response)
|
|
9665
|
-
return result;
|
|
9712
|
+
} catch {}
|
|
9713
|
+
}, 15000);
|
|
9714
|
+
},
|
|
9715
|
+
cancel() {
|
|
9716
|
+
if (keepalive)
|
|
9717
|
+
clearInterval(keepalive);
|
|
9718
|
+
if (controller)
|
|
9719
|
+
hmrClients.delete(controller);
|
|
9720
|
+
}
|
|
9721
|
+
});
|
|
9722
|
+
return new Response(stream, {
|
|
9723
|
+
headers: {
|
|
9724
|
+
"Content-Type": "text/event-stream",
|
|
9725
|
+
"Cache-Control": "no-cache, no-transform",
|
|
9726
|
+
Connection: "keep-alive",
|
|
9727
|
+
"X-Accel-Buffering": "no"
|
|
9728
|
+
}
|
|
9729
|
+
});
|
|
9666
9730
|
}
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
return routeHandler(req);
|
|
9731
|
+
if (options.onRequest) {
|
|
9732
|
+
const customResponse = await options.onRequest(req);
|
|
9733
|
+
if (customResponse)
|
|
9734
|
+
return customResponse;
|
|
9672
9735
|
}
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
const
|
|
9676
|
-
if (
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9736
|
+
const route = resolveRouteMiddleware(path);
|
|
9737
|
+
const extraNames = extraProtectedPrefixes.some((p) => path === p || path.startsWith(p.endsWith("/") ? p : `${p}/`)) ? ["auth"] : [];
|
|
9738
|
+
const requested = [...globalMiddlewareNames, ...route.names, ...extraNames];
|
|
9739
|
+
if (requested.length > 0) {
|
|
9740
|
+
const expanded = expandMiddlewareNames(requested);
|
|
9741
|
+
const cookies = parseCookies(req);
|
|
9742
|
+
const ctx = {
|
|
9743
|
+
path,
|
|
9744
|
+
url,
|
|
9745
|
+
params: route.params,
|
|
9746
|
+
cookies,
|
|
9747
|
+
redirect: (to, status = 302) => {
|
|
9748
|
+
const sep = to.includes("?") ? "&" : "?";
|
|
9749
|
+
const next = encodeURIComponent(path + (url.search || ""));
|
|
9750
|
+
return new Response(null, {
|
|
9751
|
+
status,
|
|
9752
|
+
headers: { Location: `${to}${sep}next=${next}` }
|
|
9753
|
+
});
|
|
9754
|
+
}
|
|
9755
|
+
};
|
|
9756
|
+
for (const entry of expanded) {
|
|
9757
|
+
const colon = entry.indexOf(":");
|
|
9758
|
+
const name = colon === -1 ? entry : entry.slice(0, colon);
|
|
9759
|
+
const args = colon === -1 ? [] : entry.slice(colon + 1).split(",");
|
|
9760
|
+
const handler = middlewareRegistry[name];
|
|
9761
|
+
if (!handler) {
|
|
9762
|
+
console.warn(`[stx serve] unknown middleware "${name}" on ${path}`);
|
|
9763
|
+
continue;
|
|
9764
|
+
}
|
|
9765
|
+
const result = await handler(req, ctx, ...args);
|
|
9766
|
+
if (result instanceof Response)
|
|
9767
|
+
return result;
|
|
9696
9768
|
}
|
|
9697
9769
|
}
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
if (!tableName) {
|
|
9703
|
-
return new Response(JSON.stringify({ error: "Table name required" }), {
|
|
9704
|
-
status: 400,
|
|
9705
|
-
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9706
|
-
});
|
|
9770
|
+
if (options.routes) {
|
|
9771
|
+
const routeHandler = options.routes[path];
|
|
9772
|
+
if (routeHandler) {
|
|
9773
|
+
return routeHandler(req);
|
|
9707
9774
|
}
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9775
|
+
}
|
|
9776
|
+
if (path.startsWith("/_stx/component/")) {
|
|
9777
|
+
const componentName = decodeURIComponent(path.slice("/_stx/component/".length));
|
|
9778
|
+
if (componentName) {
|
|
9779
|
+
try {
|
|
9780
|
+
const { processDirectives, defaultConfig: defaultConfig4 } = await stxModule;
|
|
9781
|
+
const componentTemplate = `<${componentName} />`;
|
|
9782
|
+
const componentOpts = {
|
|
9783
|
+
...defaultConfig4,
|
|
9784
|
+
...componentsDir && { componentsDir },
|
|
9785
|
+
...layoutsDir && { layoutsDir },
|
|
9786
|
+
...partialsDir && { partialsDir },
|
|
9787
|
+
autoShell: false
|
|
9788
|
+
};
|
|
9789
|
+
const html = await processDirectives(componentTemplate, {}, `${componentsDir}/${componentName}.stx`, componentOpts, new Set);
|
|
9790
|
+
return new Response(html, {
|
|
9791
|
+
headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders }
|
|
9792
|
+
});
|
|
9793
|
+
} catch (e) {
|
|
9794
|
+
return new Response(`<div class="stx-async-error">${e.message}</div>`, {
|
|
9795
|
+
status: 500,
|
|
9796
|
+
headers: { "Content-Type": "text/html; charset=utf-8", ...corsHeaders }
|
|
9797
|
+
});
|
|
9798
|
+
}
|
|
9713
9799
|
}
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
const dbPath = nodePath.resolve(process19.cwd(), "database/stacks.sqlite");
|
|
9717
|
-
const db = new Database(dbPath);
|
|
9800
|
+
}
|
|
9801
|
+
if (path.startsWith("/api/data/") && req.method === "POST") {
|
|
9718
9802
|
try {
|
|
9719
|
-
const
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
if (body[col] !== undefined && body[col] !== "") {
|
|
9726
|
-
columns.push(col);
|
|
9727
|
-
placeholders.push("?");
|
|
9728
|
-
values.push(body[col]);
|
|
9729
|
-
}
|
|
9730
|
-
}
|
|
9731
|
-
const now = new Date().toISOString();
|
|
9732
|
-
if (tableInfo.some((c) => c.name === "created_at")) {
|
|
9733
|
-
columns.push("created_at");
|
|
9734
|
-
placeholders.push("?");
|
|
9735
|
-
values.push(now);
|
|
9736
|
-
}
|
|
9737
|
-
if (tableInfo.some((c) => c.name === "updated_at")) {
|
|
9738
|
-
columns.push("updated_at");
|
|
9739
|
-
placeholders.push("?");
|
|
9740
|
-
values.push(now);
|
|
9803
|
+
const tableName = path.replace("/api/data/", "").split("/")[0];
|
|
9804
|
+
if (!tableName) {
|
|
9805
|
+
return new Response(JSON.stringify({ error: "Table name required" }), {
|
|
9806
|
+
status: 400,
|
|
9807
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9808
|
+
});
|
|
9741
9809
|
}
|
|
9742
|
-
if (
|
|
9743
|
-
return new Response(JSON.stringify({ error: "
|
|
9810
|
+
if (!/^[a-zA-Z_]\w*$/.test(tableName)) {
|
|
9811
|
+
return new Response(JSON.stringify({ error: "Invalid table name" }), {
|
|
9744
9812
|
status: 400,
|
|
9745
9813
|
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9746
9814
|
});
|
|
9747
9815
|
}
|
|
9748
|
-
const
|
|
9749
|
-
const
|
|
9750
|
-
const
|
|
9751
|
-
|
|
9752
|
-
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
status: 500,
|
|
9765
|
-
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9766
|
-
});
|
|
9767
|
-
} finally {
|
|
9768
|
-
db.close();
|
|
9769
|
-
}
|
|
9770
|
-
} catch {}
|
|
9771
|
-
}
|
|
9772
|
-
if (path === "/index")
|
|
9773
|
-
path = "/";
|
|
9774
|
-
if (path === "/") {
|
|
9775
|
-
const indexContent = await getRoute("/");
|
|
9776
|
-
if (!indexContent) {
|
|
9777
|
-
const homeContent = await getRoute("/home");
|
|
9778
|
-
if (homeContent) {
|
|
9779
|
-
return new Response(null, {
|
|
9780
|
-
status: 302,
|
|
9781
|
-
headers: {
|
|
9782
|
-
Location: "/home",
|
|
9783
|
-
...corsHeaders
|
|
9816
|
+
const body = await req.json();
|
|
9817
|
+
const { Database } = await import("bun:sqlite");
|
|
9818
|
+
const dbPath = nodePath.resolve(process19.cwd(), "database/stacks.sqlite");
|
|
9819
|
+
const db = new Database(dbPath);
|
|
9820
|
+
try {
|
|
9821
|
+
const tableInfo = db.query(`PRAGMA table_info("${tableName}")`).all();
|
|
9822
|
+
const validColumns = tableInfo.map((c) => c.name).filter((n) => n !== "id" && n !== "created_at" && n !== "updated_at");
|
|
9823
|
+
const columns = [];
|
|
9824
|
+
const placeholders = [];
|
|
9825
|
+
const values = [];
|
|
9826
|
+
for (const col of validColumns) {
|
|
9827
|
+
if (body[col] !== undefined && body[col] !== "") {
|
|
9828
|
+
columns.push(col);
|
|
9829
|
+
placeholders.push("?");
|
|
9830
|
+
values.push(body[col]);
|
|
9831
|
+
}
|
|
9784
9832
|
}
|
|
9785
|
-
|
|
9833
|
+
const now = new Date().toISOString();
|
|
9834
|
+
if (tableInfo.some((c) => c.name === "created_at")) {
|
|
9835
|
+
columns.push("created_at");
|
|
9836
|
+
placeholders.push("?");
|
|
9837
|
+
values.push(now);
|
|
9838
|
+
}
|
|
9839
|
+
if (tableInfo.some((c) => c.name === "updated_at")) {
|
|
9840
|
+
columns.push("updated_at");
|
|
9841
|
+
placeholders.push("?");
|
|
9842
|
+
values.push(now);
|
|
9843
|
+
}
|
|
9844
|
+
if (columns.length === 0) {
|
|
9845
|
+
return new Response(JSON.stringify({ error: "No valid fields provided" }), {
|
|
9846
|
+
status: 400,
|
|
9847
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9848
|
+
});
|
|
9849
|
+
}
|
|
9850
|
+
const query = `INSERT INTO "${tableName}" (${columns.join(", ")}) VALUES (${placeholders.join(", ")})`;
|
|
9851
|
+
const stmt = db.prepare(query);
|
|
9852
|
+
const result = stmt.run(...values);
|
|
9853
|
+
return new Response(JSON.stringify({
|
|
9854
|
+
success: true,
|
|
9855
|
+
id: result.lastInsertRowid,
|
|
9856
|
+
message: "Record created successfully"
|
|
9857
|
+
}), {
|
|
9858
|
+
status: 201,
|
|
9859
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9860
|
+
});
|
|
9861
|
+
} catch (error) {
|
|
9862
|
+
console.error("API Error:", error);
|
|
9863
|
+
return new Response(JSON.stringify({
|
|
9864
|
+
error: error.message || "Failed to create record"
|
|
9865
|
+
}), {
|
|
9866
|
+
status: 500,
|
|
9867
|
+
headers: { "Content-Type": "application/json", ...corsHeaders }
|
|
9868
|
+
});
|
|
9869
|
+
} finally {
|
|
9870
|
+
db.close();
|
|
9871
|
+
}
|
|
9872
|
+
} catch {}
|
|
9873
|
+
}
|
|
9874
|
+
if (path === "/index")
|
|
9875
|
+
path = "/";
|
|
9876
|
+
if (path === "/") {
|
|
9877
|
+
const indexContent = await getRoute("/");
|
|
9878
|
+
if (!indexContent) {
|
|
9879
|
+
const homeContent = await getRoute("/home");
|
|
9880
|
+
if (homeContent) {
|
|
9881
|
+
return new Response(null, {
|
|
9882
|
+
status: 302,
|
|
9883
|
+
headers: {
|
|
9884
|
+
Location: "/home",
|
|
9885
|
+
...corsHeaders
|
|
9886
|
+
}
|
|
9887
|
+
});
|
|
9888
|
+
}
|
|
9786
9889
|
}
|
|
9787
9890
|
}
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9795
|
-
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
-
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
|
|
9891
|
+
const content = await getRoute(path);
|
|
9892
|
+
if (content) {
|
|
9893
|
+
const isSpaNav = req.headers.get("X-STX-Router") === "true";
|
|
9894
|
+
if (isSpaNav) {
|
|
9895
|
+
const layoutMatch = content.match(/<!-- stx-layout: ([^ ]+) -->/);
|
|
9896
|
+
const pageLayout = layoutMatch ? layoutMatch[1] : "default";
|
|
9897
|
+
const groupMetaMatch = content.match(/<meta\b[^>]*name=["']stx-layout-group["'][^>]*content=["']([^"']+)["'][^>]*>/i);
|
|
9898
|
+
const pageLayoutGroup = i18nConfig && i18nLocale ? `i18n:${i18nLocale}` : groupMetaMatch?.[1] || deriveLayoutGroup(pageLayout);
|
|
9899
|
+
let fragment = content;
|
|
9900
|
+
const headStyles = [];
|
|
9901
|
+
const headMatch = content.match(/<head\b[^>]*>([\s\S]*?)<\/head>/i);
|
|
9902
|
+
if (headMatch) {
|
|
9903
|
+
const headContent = headMatch[1];
|
|
9904
|
+
let styleMatch;
|
|
9905
|
+
const styleRe = /<style\b[^>]*>[\s\S]*?<\/style>/gi;
|
|
9906
|
+
while ((styleMatch = styleRe.exec(headContent)) !== null) {
|
|
9907
|
+
if (styleMatch[0].includes("data-crosswind")) {
|
|
9908
|
+
const cssContent = styleMatch[0].replace(/<style[^>]*>/, "").replace(/<\/style>/, "");
|
|
9909
|
+
const hiddenRule = cssContent.indexOf("[hidden]");
|
|
9910
|
+
if (hiddenRule !== -1) {
|
|
9911
|
+
const afterPreflight = cssContent.indexOf("}", hiddenRule) + 1;
|
|
9912
|
+
const utilities = cssContent.slice(afterPreflight).trim();
|
|
9913
|
+
if (utilities) {
|
|
9914
|
+
headStyles.push(`<style data-crosswind="fragment">${utilities}</style>`);
|
|
9915
|
+
}
|
|
9812
9916
|
}
|
|
9917
|
+
continue;
|
|
9813
9918
|
}
|
|
9814
|
-
|
|
9919
|
+
headStyles.push(styleMatch[0]);
|
|
9815
9920
|
}
|
|
9816
|
-
headStyles.push(styleMatch[0]);
|
|
9817
9921
|
}
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9922
|
+
const mainOpenMatch = fragment.match(/<main\b[^>]*>/i);
|
|
9923
|
+
const mainCloseIdx = fragment.lastIndexOf("</main>");
|
|
9924
|
+
if (mainOpenMatch && mainCloseIdx !== -1) {
|
|
9925
|
+
const bodyMatch = content.match(/<body\b[^>]*>/i);
|
|
9926
|
+
if (bodyMatch) {
|
|
9927
|
+
const bodyStart = bodyMatch.index + bodyMatch[0].length;
|
|
9928
|
+
const mainIdx = mainOpenMatch.index;
|
|
9929
|
+
const beforeMain = content.slice(bodyStart, mainIdx);
|
|
9930
|
+
let bodyStyleMatch;
|
|
9931
|
+
const bodyStyleRe = /<style\b[^>]*>[\s\S]*?<\/style>/gi;
|
|
9932
|
+
while ((bodyStyleMatch = bodyStyleRe.exec(beforeMain)) !== null) {
|
|
9933
|
+
headStyles.push(bodyStyleMatch[0]);
|
|
9934
|
+
}
|
|
9831
9935
|
}
|
|
9936
|
+
const mainStart = mainOpenMatch.index + mainOpenMatch[0].length;
|
|
9937
|
+
fragment = fragment.slice(mainStart, mainCloseIdx).trim();
|
|
9832
9938
|
}
|
|
9833
|
-
const
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
|
|
9844
|
-
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
fragment = fragment.replace(/<script data-stx-scoped>\s*;?\(function\(\)\s*\{[\s\S]*?<\/script>/g, "");
|
|
9852
|
-
const clearStale = "<script data-stx-page>if(window.stx)window.stx._latestSetup=null;</script>";
|
|
9853
|
-
fragment = `${headStyles.join(`
|
|
9939
|
+
const pageSetupScripts = [];
|
|
9940
|
+
const allScriptRe = /<script\b[^>]*data-stx-scoped[^>]*>[\s\S]*?<\/script>/gi;
|
|
9941
|
+
let setupMatch;
|
|
9942
|
+
while ((setupMatch = allScriptRe.exec(content)) !== null) {
|
|
9943
|
+
const scriptContent = setupMatch[0];
|
|
9944
|
+
if (scriptContent.includes("__stx_early_mounts"))
|
|
9945
|
+
continue;
|
|
9946
|
+
if (scriptContent.includes("data-stx-reactive") && scriptContent.includes("window.__stx_reactive"))
|
|
9947
|
+
continue;
|
|
9948
|
+
pageSetupScripts.push(scriptContent);
|
|
9949
|
+
}
|
|
9950
|
+
const bridgeInitRe = /<script\b[^>]*data-stx-reactive[^>]*>(?![\s\S]*window\.__stx_reactive)[\s\S]*?<\/script>/gi;
|
|
9951
|
+
while ((setupMatch = bridgeInitRe.exec(content)) !== null) {
|
|
9952
|
+
pageSetupScripts.push(setupMatch[0]);
|
|
9953
|
+
}
|
|
9954
|
+
fragment = fragment.replace(/<script data-stx-scoped>\s*;?\(function\(\)\s*\{[\s\S]*?<\/script>/g, "");
|
|
9955
|
+
const clearStale = "<script data-stx-page>if(window.stx)window.stx._latestSetup=null;</script>";
|
|
9956
|
+
fragment = `${headStyles.join(`
|
|
9854
9957
|
`)}
|
|
9855
9958
|
${fragment}
|
|
9856
9959
|
${clearStale}
|
|
9857
9960
|
${pageSetupScripts.join(`
|
|
9858
9961
|
`)}`;
|
|
9859
|
-
|
|
9962
|
+
return new Response(fragment, {
|
|
9963
|
+
headers: {
|
|
9964
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
9965
|
+
"X-STX-Fragment": "true",
|
|
9966
|
+
"X-STX-Layout": pageLayout,
|
|
9967
|
+
"X-STX-Layout-Group": pageLayoutGroup,
|
|
9968
|
+
"Cache-Control": "no-store",
|
|
9969
|
+
...corsHeaders
|
|
9970
|
+
}
|
|
9971
|
+
});
|
|
9972
|
+
}
|
|
9973
|
+
let cleaned = content;
|
|
9974
|
+
let runtimeCount = 0;
|
|
9975
|
+
cleaned = content.replace(/<script data-stx-scoped>\(function\(\)\{'use strict';var cloakStyle[\s\S]*?<\/script>/g, (match) => {
|
|
9976
|
+
runtimeCount++;
|
|
9977
|
+
return runtimeCount === 1 ? match : "";
|
|
9978
|
+
});
|
|
9979
|
+
return new Response(injectHmrClient(cleaned), {
|
|
9860
9980
|
headers: {
|
|
9861
9981
|
"Content-Type": "text/html; charset=utf-8",
|
|
9862
|
-
"
|
|
9863
|
-
"X-STX-Layout": pageLayout,
|
|
9864
|
-
"X-STX-Layout-Group": pageLayoutGroup,
|
|
9865
|
-
"Cache-Control": "no-cache",
|
|
9982
|
+
"Cache-Control": "no-store",
|
|
9866
9983
|
...corsHeaders
|
|
9867
9984
|
}
|
|
9868
9985
|
});
|
|
9869
9986
|
}
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
|
|
9878
|
-
|
|
9879
|
-
"Cache-Control": "no-cache",
|
|
9880
|
-
...corsHeaders
|
|
9881
|
-
}
|
|
9882
|
-
});
|
|
9883
|
-
}
|
|
9884
|
-
const contentWithExt = await getRoute(`${path}.html`);
|
|
9885
|
-
if (contentWithExt) {
|
|
9886
|
-
return new Response(injectHmrClient(contentWithExt), {
|
|
9887
|
-
headers: {
|
|
9888
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
9889
|
-
"Cache-Control": "no-cache",
|
|
9890
|
-
...corsHeaders
|
|
9891
|
-
}
|
|
9892
|
-
});
|
|
9893
|
-
}
|
|
9894
|
-
if (path.startsWith("/chunk-") || path.endsWith(".js") || path.endsWith(".css")) {
|
|
9895
|
-
try {
|
|
9896
|
-
const buildFile = Bun.file(`.stx${path}`);
|
|
9897
|
-
if (await buildFile.exists()) {
|
|
9898
|
-
const ext = path.split(".").pop()?.toLowerCase();
|
|
9899
|
-
const contentType = ext === "css" ? "text/css" : ext === "js" ? "application/javascript" : "text/plain";
|
|
9900
|
-
return new Response(buildFile, {
|
|
9901
|
-
headers: {
|
|
9902
|
-
"Content-Type": contentType,
|
|
9903
|
-
"Cache-Control": "no-cache"
|
|
9904
|
-
}
|
|
9905
|
-
});
|
|
9906
|
-
}
|
|
9907
|
-
} catch {}
|
|
9908
|
-
}
|
|
9909
|
-
if (path.startsWith("/assets/") || path.startsWith("/resources/assets/")) {
|
|
9910
|
-
await ensureAssets();
|
|
9911
|
-
let assetPathname;
|
|
9912
|
-
try {
|
|
9913
|
-
assetPathname = decodeURIComponent(path);
|
|
9914
|
-
} catch {
|
|
9915
|
-
return new Response("Invalid asset path", { status: 400 });
|
|
9987
|
+
const contentWithExt = await getRoute(`${path}.html`);
|
|
9988
|
+
if (contentWithExt) {
|
|
9989
|
+
return new Response(injectHmrClient(contentWithExt), {
|
|
9990
|
+
headers: {
|
|
9991
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
9992
|
+
"Cache-Control": "no-store",
|
|
9993
|
+
...corsHeaders
|
|
9994
|
+
}
|
|
9995
|
+
});
|
|
9916
9996
|
}
|
|
9917
|
-
if (
|
|
9918
|
-
return new Response("Invalid asset path", { status: 400 });
|
|
9919
|
-
for (const assetPath of assetRequestPaths(assetPathname)) {
|
|
9997
|
+
if (path.startsWith("/chunk-") || path.endsWith(".js") || path.endsWith(".css")) {
|
|
9920
9998
|
try {
|
|
9921
|
-
const
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
const
|
|
9925
|
-
|
|
9926
|
-
return bundleBrowserAsset(filePath);
|
|
9927
|
-
return new Response(file, {
|
|
9999
|
+
const buildFile = Bun.file(`.stx${path}`);
|
|
10000
|
+
if (await buildFile.exists()) {
|
|
10001
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
10002
|
+
const contentType = ext === "css" ? "text/css" : ext === "js" ? "application/javascript" : "text/plain";
|
|
10003
|
+
return new Response(buildFile, {
|
|
9928
10004
|
headers: {
|
|
9929
|
-
"Content-Type":
|
|
9930
|
-
"Cache-Control": "no-
|
|
10005
|
+
"Content-Type": contentType,
|
|
10006
|
+
"Cache-Control": "no-store"
|
|
9931
10007
|
}
|
|
9932
10008
|
});
|
|
9933
10009
|
}
|
|
10010
|
+
} catch {}
|
|
10011
|
+
}
|
|
10012
|
+
if (path.startsWith("/assets/") || path.startsWith("/resources/assets/")) {
|
|
10013
|
+
await ensureAssets();
|
|
10014
|
+
let assetPathname;
|
|
10015
|
+
try {
|
|
10016
|
+
assetPathname = decodeURIComponent(path);
|
|
9934
10017
|
} catch {
|
|
9935
|
-
|
|
10018
|
+
return new Response("Invalid asset path", { status: 400 });
|
|
9936
10019
|
}
|
|
9937
|
-
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
const publicRoot = nodePath.resolve(process19.cwd(), publicDir);
|
|
9941
|
-
let safePathname;
|
|
9942
|
-
try {
|
|
9943
|
-
safePathname = decodeURIComponent(path);
|
|
9944
|
-
} catch {
|
|
9945
|
-
safePathname = path;
|
|
9946
|
-
}
|
|
9947
|
-
if (!safePathname.includes("\x00")) {
|
|
9948
|
-
const resolvedPath = nodePath.resolve(publicRoot, `.${safePathname}`);
|
|
9949
|
-
const isInsidePublicRoot = resolvedPath === publicRoot || resolvedPath.startsWith(`${publicRoot}${nodePath.sep}`);
|
|
9950
|
-
if (isInsidePublicRoot) {
|
|
10020
|
+
if (!isSafeAssetPath(assetPathname))
|
|
10021
|
+
return new Response("Invalid asset path", { status: 400 });
|
|
10022
|
+
for (const assetPath of assetRequestPaths(assetPathname)) {
|
|
9951
10023
|
try {
|
|
9952
|
-
const
|
|
10024
|
+
const filePath = nodePath.resolve(process19.cwd(), `.${assetPath}`);
|
|
10025
|
+
const file = Bun.file(filePath);
|
|
9953
10026
|
if (await file.exists()) {
|
|
9954
|
-
const
|
|
9955
|
-
if (
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
|
|
9963
|
-
}
|
|
10027
|
+
const ext = getAssetExtension(assetPath);
|
|
10028
|
+
if (isBundledAssetExtension(ext))
|
|
10029
|
+
return bundleBrowserAsset(filePath);
|
|
10030
|
+
return new Response(file, {
|
|
10031
|
+
headers: {
|
|
10032
|
+
"Content-Type": staticContentTypes[ext || ""] || "application/octet-stream",
|
|
10033
|
+
"Cache-Control": "no-store"
|
|
10034
|
+
}
|
|
10035
|
+
});
|
|
9964
10036
|
}
|
|
9965
|
-
} catch {
|
|
10037
|
+
} catch {
|
|
10038
|
+
continue;
|
|
10039
|
+
}
|
|
9966
10040
|
}
|
|
9967
10041
|
}
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
10042
|
+
if ((req.method === "GET" || req.method === "HEAD") && path !== "/") {
|
|
10043
|
+
const publicRoot = nodePath.resolve(process19.cwd(), publicDir);
|
|
10044
|
+
let safePathname;
|
|
10045
|
+
try {
|
|
10046
|
+
safePathname = decodeURIComponent(path);
|
|
10047
|
+
} catch {
|
|
10048
|
+
safePathname = path;
|
|
10049
|
+
}
|
|
10050
|
+
if (!safePathname.includes("\x00")) {
|
|
10051
|
+
const resolvedPath = nodePath.resolve(publicRoot, `.${safePathname}`);
|
|
10052
|
+
const isInsidePublicRoot = resolvedPath === publicRoot || resolvedPath.startsWith(`${publicRoot}${nodePath.sep}`);
|
|
10053
|
+
if (isInsidePublicRoot) {
|
|
10054
|
+
try {
|
|
10055
|
+
const file = Bun.file(resolvedPath);
|
|
10056
|
+
if (await file.exists()) {
|
|
10057
|
+
const stat4 = await file.stat().catch(() => null);
|
|
10058
|
+
if (stat4 && !stat4.isDirectory()) {
|
|
10059
|
+
const ext = resolvedPath.split(".").pop()?.toLowerCase();
|
|
10060
|
+
return new Response(file, {
|
|
10061
|
+
headers: {
|
|
10062
|
+
"Content-Type": staticContentTypes[ext || ""] || "application/octet-stream",
|
|
10063
|
+
"Cache-Control": "no-store"
|
|
10064
|
+
}
|
|
10065
|
+
});
|
|
10066
|
+
}
|
|
10067
|
+
}
|
|
10068
|
+
} catch {}
|
|
10069
|
+
}
|
|
9981
10070
|
}
|
|
9982
10071
|
}
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
route2 = route2.slice(6);
|
|
10072
|
+
if (path === "/favicon.ico") {
|
|
10073
|
+
return new Response(null, { status: 204 });
|
|
9986
10074
|
}
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
10075
|
+
const files = await discoverFiles();
|
|
10076
|
+
const availableRoutes = [];
|
|
10077
|
+
for (const filePath of files) {
|
|
10078
|
+
let normalizedPath = filePath.replace(/^\.\//, "").replace(/\\/g, "/");
|
|
10079
|
+
for (const pattern of patterns) {
|
|
10080
|
+
const normalizedPattern = pattern.replace(/\\/g, "/").replace(/\/$/, "");
|
|
10081
|
+
if (normalizedPath.startsWith(`${normalizedPattern}/`)) {
|
|
10082
|
+
normalizedPath = normalizedPath.slice(normalizedPattern.length + 1);
|
|
10083
|
+
break;
|
|
10084
|
+
}
|
|
10085
|
+
}
|
|
10086
|
+
let route2 = normalizedPath.replace(/\.(stx|md|html)$/, "");
|
|
10087
|
+
if (route2.startsWith("pages/")) {
|
|
10088
|
+
route2 = route2.slice(6);
|
|
10089
|
+
}
|
|
10090
|
+
availableRoutes.push(`<li><a href="/${route2}">/${route2}</a></li>`);
|
|
10091
|
+
}
|
|
10092
|
+
const routesList = availableRoutes.join(`
|
|
9990
10093
|
`);
|
|
9991
|
-
|
|
10094
|
+
return new Response(injectHmrClient(`
|
|
9992
10095
|
<!DOCTYPE html>
|
|
9993
10096
|
<html>
|
|
9994
10097
|
<head>
|
|
@@ -10016,9 +10119,13 @@ ${pageSetupScripts.join(`
|
|
|
10016
10119
|
</body>
|
|
10017
10120
|
</html>
|
|
10018
10121
|
`), {
|
|
10019
|
-
|
|
10020
|
-
|
|
10021
|
-
|
|
10122
|
+
status: 404,
|
|
10123
|
+
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
10124
|
+
});
|
|
10125
|
+
} finally {
|
|
10126
|
+
activeServeLocale = null;
|
|
10127
|
+
activeServeSearch = "";
|
|
10128
|
+
}
|
|
10022
10129
|
})();
|
|
10023
10130
|
return applyI18nToResponse(_i18nResp, i18nLocale ?? (i18nConfig?.defaultLocale ?? "en"), path);
|
|
10024
10131
|
}
|
|
@@ -10092,5 +10199,6 @@ if (import.meta.main) {
|
|
|
10092
10199
|
}
|
|
10093
10200
|
export {
|
|
10094
10201
|
serve,
|
|
10095
|
-
bundleBrowserAsset
|
|
10202
|
+
bundleBrowserAsset,
|
|
10203
|
+
buildDynamicRouteRegexes
|
|
10096
10204
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-plugin-stx",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.69",
|
|
5
5
|
"description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"typecheck": "bun tsc --noEmit"
|
|
74
74
|
},
|
|
75
75
|
"dependencies": {
|
|
76
|
-
"@stacksjs/stx": "0.2.
|
|
77
|
-
"stx-router": "0.2.
|
|
76
|
+
"@stacksjs/stx": "0.2.69",
|
|
77
|
+
"stx-router": "0.2.69"
|
|
78
78
|
}
|
|
79
79
|
}
|