bun-plugin-stx 0.2.309 → 0.2.310
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-ahmasn2t.js → chunk-zt4e86p1.js} +30 -8
- package/dist/serve.d.ts +18 -0
- package/dist/serve.js +48 -11
- package/package.json +1 -1
|
@@ -1468,8 +1468,10 @@ else {
|
|
|
1468
1468
|
// Before the swap: add each sheet the page does not have yet, as
|
|
1469
1469
|
// media="print" so it downloads without restyling the page still on screen.
|
|
1470
1470
|
// Returns a promise for them to finish (load OR error, capped at
|
|
1471
|
-
// cssLoadTimeout so a slow
|
|
1472
|
-
//
|
|
1471
|
+
// cssLoadTimeout so a slow sheet never stalls navigation), or null when
|
|
1472
|
+
// nothing new is needed and the swap can go ahead in the same turn. The
|
|
1473
|
+
// promise resolves false when a sheet failed outright, and the caller then
|
|
1474
|
+
// navigates in full rather than swap in markup that has no styles.
|
|
1473
1475
|
function preloadGeneratedCss(hrefs,base){
|
|
1474
1476
|
var pending=[];
|
|
1475
1477
|
hrefs.forEach(function(href){
|
|
@@ -1490,14 +1492,34 @@ else {
|
|
|
1490
1492
|
link.setAttribute('data-stx-css-pending','');
|
|
1491
1493
|
link.__stxCssReady=new Promise(function(resolve){
|
|
1492
1494
|
var timer=setTimeout(finish,o.cssLoadTimeout);
|
|
1493
|
-
function finish(){
|
|
1494
|
-
|
|
1495
|
-
|
|
1495
|
+
function finish(failed){
|
|
1496
|
+
clearTimeout(timer);link.onload=null;link.onerror=null;link.__stxCssReady=null;
|
|
1497
|
+
// A sheet that failed (a 5xx, a dropped connection) is gone for good:
|
|
1498
|
+
// swapping anyway painted the page with only the utilities the
|
|
1499
|
+
// previous page happened to share, which reads as a broken layout.
|
|
1500
|
+
// Drop the dead <link> so a retry fetches it again, and report it.
|
|
1501
|
+
if(failed===true&&link.parentNode)link.parentNode.removeChild(link);
|
|
1502
|
+
resolve(failed!==true);
|
|
1503
|
+
}
|
|
1504
|
+
link.onload=function(){finish(false)};
|
|
1505
|
+
link.onerror=function(){finish(true)};
|
|
1496
1506
|
});
|
|
1497
1507
|
pending.push(link.__stxCssReady);
|
|
1498
1508
|
document.head.appendChild(link);
|
|
1499
1509
|
});
|
|
1500
|
-
return pending.length?Promise.all(pending):null;
|
|
1510
|
+
return pending.length?Promise.all(pending).then(function(results){return results.every(function(ok){return ok!==false})}):null;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
// Swap once the destination's sheets are in, or hand the navigation to the
|
|
1514
|
+
// browser when one could not be fetched \u2014 a full load retries the sheet.
|
|
1515
|
+
function afterCss(ready,url,swapNow){
|
|
1516
|
+
if(!ready)return swapNow();
|
|
1517
|
+
return ready.then(function(ok){
|
|
1518
|
+
if(ok)return swapNow();
|
|
1519
|
+
log('[router] stylesheet failed to load \u2014 full navigation to:',url);
|
|
1520
|
+
location.href=url;
|
|
1521
|
+
return false;
|
|
1522
|
+
});
|
|
1501
1523
|
}
|
|
1502
1524
|
|
|
1503
1525
|
// At the swap: make the destination's sheets live and move them to the end
|
|
@@ -1772,7 +1794,7 @@ else {
|
|
|
1772
1794
|
// jumps. Cleanup waits with it so the outgoing page stays live meanwhile.
|
|
1773
1795
|
// With nothing new to load this runs in the same turn, as it always did.
|
|
1774
1796
|
var fragCssReady=preloadGeneratedCss(fragmentCssHrefs(html),location.href);
|
|
1775
|
-
return fragCssReady
|
|
1797
|
+
return afterCss(fragCssReady,url,startFragSwap);
|
|
1776
1798
|
}
|
|
1777
1799
|
|
|
1778
1800
|
// Full document mode: parse with DOMParser and extract container content
|
|
@@ -2214,7 +2236,7 @@ else {
|
|
|
2214
2236
|
});
|
|
2215
2237
|
}
|
|
2216
2238
|
var docCssReady=preloadGeneratedCss(docCssHrefs,docCssBase);
|
|
2217
|
-
return docCssReady
|
|
2239
|
+
return afterCss(docCssReady,url,startSwap);
|
|
2218
2240
|
}
|
|
2219
2241
|
|
|
2220
2242
|
// \u2500\u2500 Link interception \u2500\u2500
|
package/dist/serve.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ export declare function extractServerScriptsFromTemplate(content: string): {
|
|
|
11
11
|
serverScripts: string[]
|
|
12
12
|
templateContent: string
|
|
13
13
|
};
|
|
14
|
+
/** The params as a script-safe object literal. */
|
|
15
|
+
export declare function serializeRouteParams(params: Record<string, string>): string;
|
|
16
|
+
/** Put one request's params into a cached dynamic-route shell. */
|
|
17
|
+
export declare function fillRouteParams(html: string, params: Record<string, string>): string;
|
|
18
|
+
/**
|
|
19
|
+
* Whether a page's server scripts read its route params — `params`, or a
|
|
20
|
+
* segment by its bare name (`[id].stx` binds `id`). Such a page renders per
|
|
21
|
+
* record and must not share one cached render across them. Deliberately
|
|
22
|
+
* coarse: a comment or an unrelated local spelled the same only costs the
|
|
23
|
+
* cache, never correctness.
|
|
24
|
+
*/
|
|
25
|
+
export declare function serverScriptsReadParams(serverScripts: string[], paramNames: string[]): boolean;
|
|
14
26
|
/**
|
|
15
27
|
* A token to mint for this request, or null to leave it alone.
|
|
16
28
|
*
|
|
@@ -199,6 +211,12 @@ export declare function serve(options: ServeOptions): Promise<void>;
|
|
|
199
211
|
* own templates, including a framework's templates vendored into it.
|
|
200
212
|
*/
|
|
201
213
|
export declare function projectUsesImageBuiltins(root: string): Promise<boolean>;
|
|
214
|
+
/**
|
|
215
|
+
* Stands in for a dynamic route's params in a cached shell. Not valid
|
|
216
|
+
* JavaScript on its own, so a shell that escaped without being filled fails
|
|
217
|
+
* loudly instead of running with somebody else's params.
|
|
218
|
+
*/
|
|
219
|
+
export declare const ROUTE_PARAMS_PLACEHOLDER: '__STX_ROUTE_PARAMS__';
|
|
202
220
|
/**
|
|
203
221
|
* The cookie name a double-submit CSRF check reads.
|
|
204
222
|
*
|
package/dist/serve.js
CHANGED
|
@@ -8851,6 +8851,19 @@ function extractServerScriptsFromTemplate(content) {
|
|
|
8851
8851
|
retained.push(content.slice(retainedFrom));
|
|
8852
8852
|
return { serverScripts, templateContent: retained.join("") };
|
|
8853
8853
|
}
|
|
8854
|
+
var ROUTE_PARAMS_PLACEHOLDER = "__STX_ROUTE_PARAMS__";
|
|
8855
|
+
function serializeRouteParams(params) {
|
|
8856
|
+
return JSON.stringify(params).replace(/</g, "\\u003C").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
8857
|
+
}
|
|
8858
|
+
function fillRouteParams(html, params) {
|
|
8859
|
+
const serialized = serializeRouteParams(params);
|
|
8860
|
+
return html.replace(ROUTE_PARAMS_PLACEHOLDER, () => serialized);
|
|
8861
|
+
}
|
|
8862
|
+
function serverScriptsReadParams(serverScripts, paramNames) {
|
|
8863
|
+
const names = ["params", ...paramNames].map((name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
8864
|
+
const pattern = new RegExp(`(?:^|[^\\w$.])(?:${names.join("|")})(?![\\w$])`);
|
|
8865
|
+
return serverScripts.some((script) => pattern.test(script));
|
|
8866
|
+
}
|
|
8854
8867
|
var CSRF_COOKIE = "X-CSRF-Token";
|
|
8855
8868
|
function csrfTokenToMint(req, cookies) {
|
|
8856
8869
|
const method = (req.method || "GET").toUpperCase();
|
|
@@ -9713,7 +9726,7 @@ function __stxOverlay(errs){
|
|
|
9713
9726
|
pageMiddlewarePatterns.length = 0;
|
|
9714
9727
|
await Promise.all(files.map((f) => detectPageMiddleware(f)));
|
|
9715
9728
|
try {
|
|
9716
|
-
const { Router } = await import("./chunk-
|
|
9729
|
+
const { Router } = await import("./chunk-zt4e86p1.js");
|
|
9717
9730
|
const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
|
|
9718
9731
|
const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName() });
|
|
9719
9732
|
if (!options.quiet)
|
|
@@ -10114,12 +10127,6 @@ function __stxOverlay(errs){
|
|
|
10114
10127
|
if (reqCtx)
|
|
10115
10128
|
reqCtx.responseStatus = extractPageResponseStatus(content) ?? 200;
|
|
10116
10129
|
const { serverScripts: dynServerScripts, templateContent } = extractServerScriptsFromTemplate(content);
|
|
10117
|
-
const context = {
|
|
10118
|
-
__filename: filePath,
|
|
10119
|
-
__dirname: nodePath.dirname(filePath),
|
|
10120
|
-
__route: routePath,
|
|
10121
|
-
__stx_runtime_head: {}
|
|
10122
|
-
};
|
|
10123
10130
|
const paramsObj = {};
|
|
10124
10131
|
for (let i = 0;i < paramNames.length; i++) {
|
|
10125
10132
|
let value = paramValues[i] ?? "";
|
|
@@ -10128,12 +10135,31 @@ function __stxOverlay(errs){
|
|
|
10128
10135
|
} catch {}
|
|
10129
10136
|
paramsObj[paramNames[i]] = value;
|
|
10130
10137
|
}
|
|
10138
|
+
const isMutating = !!reqCtx && reqCtx.method !== "GET" && reqCtx.method !== "HEAD";
|
|
10139
|
+
const skipCacheHint = /(?:^|[^\w$])__stx_skip_cache\s*=\s*true/.test(content);
|
|
10140
|
+
const cacheShell = ENABLE_HTML_CACHE && RENDER_CACHE_VARY === "source" && paramNames.length > 0 && !isMutating && !skipCacheHint && !serverScriptsReadParams(dynServerScripts, paramNames);
|
|
10141
|
+
if (reqCtx)
|
|
10142
|
+
reqCtx.params = paramsObj;
|
|
10143
|
+
if (cacheShell) {
|
|
10144
|
+
const cachedEntry = htmlCache.get(filePath);
|
|
10145
|
+
if (cachedEntry && await templateSignatureFresh(cachedEntry.signature)) {
|
|
10146
|
+
if (reqCtx) {
|
|
10147
|
+
reqCtx.responseStatus = cachedEntry.status;
|
|
10148
|
+
reqCtx.responseHeaders = cachedEntry.headers;
|
|
10149
|
+
}
|
|
10150
|
+
return fillRouteParams(cachedEntry.html, paramsObj);
|
|
10151
|
+
}
|
|
10152
|
+
}
|
|
10153
|
+
const context = {
|
|
10154
|
+
__filename: filePath,
|
|
10155
|
+
__dirname: nodePath.dirname(filePath),
|
|
10156
|
+
__route: routePath,
|
|
10157
|
+
__stx_runtime_head: {}
|
|
10158
|
+
};
|
|
10131
10159
|
for (const name of paramNames) {
|
|
10132
10160
|
context[name] = paramsObj[name];
|
|
10133
10161
|
}
|
|
10134
10162
|
context.params = paramsObj;
|
|
10135
|
-
if (reqCtx)
|
|
10136
|
-
reqCtx.params = paramsObj;
|
|
10137
10163
|
const { processDirectives, extractVariables, defaultConfig: defaultConfig4, injectRouterScript: injectRouter } = await stxModule;
|
|
10138
10164
|
injectServeLocaleContext(context);
|
|
10139
10165
|
injectServeRequestContext(context, reqCtx);
|
|
@@ -10172,7 +10198,7 @@ function __stxOverlay(errs){
|
|
|
10172
10198
|
output = await processDirectives(output, context, filePath, config5, dependencies);
|
|
10173
10199
|
applyRecordedResponse(context, reqCtx);
|
|
10174
10200
|
if (paramNames.length > 0) {
|
|
10175
|
-
const serializedParams =
|
|
10201
|
+
const serializedParams = cacheShell ? ROUTE_PARAMS_PLACEHOLDER : serializeRouteParams(paramsObj);
|
|
10176
10202
|
const paramsScript = `<script data-stx-route-params>(function(){var p=${serializedParams};window.__stx_rp=p;if(window.stx){window.stx._rp=p;if(window.stx.setRouteParams)window.stx.setRouteParams(p)}})()</script>`;
|
|
10177
10203
|
if (output.includes("</head>")) {
|
|
10178
10204
|
output = output.replace("</head>", `${paramsScript}
|
|
@@ -10191,7 +10217,14 @@ ${output}`;
|
|
|
10191
10217
|
return match;
|
|
10192
10218
|
return "";
|
|
10193
10219
|
});
|
|
10194
|
-
|
|
10220
|
+
if (!cacheShell)
|
|
10221
|
+
return output;
|
|
10222
|
+
const recordedResponse = readResponseStatus(context) !== undefined || !!readResponseHeaders(context);
|
|
10223
|
+
if (!context.__stx_skip_cache && !recordedResponse && isRenderableCacheCandidate(output) && placeholdersAreReady) {
|
|
10224
|
+
const signature = await buildTemplateSignature(filePath, dependencies);
|
|
10225
|
+
htmlCache.set(filePath, { html: output, signature, status: reqCtx?.responseStatus ?? 200, headers: reqCtx?.responseHeaders });
|
|
10226
|
+
}
|
|
10227
|
+
return fillRouteParams(output, paramsObj);
|
|
10195
10228
|
}
|
|
10196
10229
|
const startTime = performance.now();
|
|
10197
10230
|
await discoverFiles();
|
|
@@ -11148,7 +11181,9 @@ export {
|
|
|
11148
11181
|
usableErrorPage,
|
|
11149
11182
|
staticCacheControl,
|
|
11150
11183
|
sharedScriptCacheControl,
|
|
11184
|
+
serverScriptsReadParams,
|
|
11151
11185
|
serve,
|
|
11186
|
+
serializeRouteParams,
|
|
11152
11187
|
routeSpecificity,
|
|
11153
11188
|
responseTakesCsrfCookie,
|
|
11154
11189
|
resolveServeOpenUrl,
|
|
@@ -11159,6 +11194,7 @@ export {
|
|
|
11159
11194
|
isRenderableCacheCandidate,
|
|
11160
11195
|
isRenderFailure,
|
|
11161
11196
|
isProductionServe,
|
|
11197
|
+
fillRouteParams,
|
|
11162
11198
|
extractServerScriptsFromTemplate,
|
|
11163
11199
|
csrfTokenToMint,
|
|
11164
11200
|
csrfCookieHeader,
|
|
@@ -11166,5 +11202,6 @@ export {
|
|
|
11166
11202
|
buildDynamicRouteRegexes,
|
|
11167
11203
|
boundedCache,
|
|
11168
11204
|
SHARED_SCRIPT_PATH,
|
|
11205
|
+
ROUTE_PARAMS_PLACEHOLDER,
|
|
11169
11206
|
CSRF_COOKIE
|
|
11170
11207
|
};
|
package/package.json
CHANGED