@tokenoftrust/storefront-runner 3.3.2 → 3.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -100,10 +100,7 @@ export function sessionAdmitsHost(
|
|
|
100
100
|
return sessionHostCapability(record, hostResource, nowSeconds) !== null;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
export function parseGateMode(raw: string | null | undefined): GateMode {
|
|
105
|
-
return (raw ?? "").trim().toLowerCase() === "login" ? "login" : "password";
|
|
106
|
-
}
|
|
103
|
+
export { parseGateMode } from "../shared/gateMode.js";
|
|
107
104
|
|
|
108
105
|
/**
|
|
109
106
|
* Paths that MUST stay reachable without a session, or the visitor could never
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The document's server response time for the evidence panel: the `total` the Worker stamps in
|
|
3
|
+
* `Server-Timing` (`lib/observability/shared/serverTiming.ts`) next to the time this self-fetch
|
|
4
|
+
* waited for the response headers (TTFB as seen from the Worker). Advisory — never gates promotion.
|
|
5
|
+
*
|
|
6
|
+
* The self-fetch carries the viewer's preview grant so it measures the render a reviewer gets. A
|
|
7
|
+
* gate page or any non-200 answer is not that render, so it is reported as not measured rather
|
|
8
|
+
* than as a number.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface ServerResponseTime {
|
|
12
|
+
measured: true;
|
|
13
|
+
/** `total;dur` from the document's `Server-Timing`, or null when the header is absent. */
|
|
14
|
+
serverTotalMs: number | null;
|
|
15
|
+
/** Wall time until the response headers arrived. */
|
|
16
|
+
ttfbMs: number;
|
|
17
|
+
/** The isolate was serving its first request (`isolate;desc="cold"`). */
|
|
18
|
+
cold: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ServerResponseTimeUnmeasured {
|
|
22
|
+
measured: false;
|
|
23
|
+
reason: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Pull `total;dur` and the cold marker out of a `Server-Timing` header value. */
|
|
27
|
+
export function parseServerTiming(header: string | null | undefined): Pick<ServerResponseTime, "serverTotalMs" | "cold"> {
|
|
28
|
+
if (!header) return { serverTotalMs: null, cold: false };
|
|
29
|
+
const entries = header.split(",").map((e) => e.trim());
|
|
30
|
+
const total = entries.find((e) => /^total(;|$)/.test(e))?.match(/;\s*dur=([0-9.]+)/);
|
|
31
|
+
return {
|
|
32
|
+
serverTotalMs: total ? Number(total[1]) : null,
|
|
33
|
+
cold: entries.some((e) => /^isolate;\s*desc="cold"$/.test(e)),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The URL and headers that make a self-fetch of `path` the viewer's own render: the request's
|
|
39
|
+
* `__preview` grant (query) and cookies are forwarded.
|
|
40
|
+
*/
|
|
41
|
+
export function viewerRenderRequest(requestUrl: string, path: string, cookie: string | null): { url: URL; headers: Headers } {
|
|
42
|
+
const source = new URL(requestUrl);
|
|
43
|
+
const url = new URL(path, source.origin);
|
|
44
|
+
const grant = source.searchParams.get("__preview");
|
|
45
|
+
if (grant) url.searchParams.set("__preview", grant);
|
|
46
|
+
const headers = new Headers();
|
|
47
|
+
if (cookie) headers.set("cookie", cookie);
|
|
48
|
+
return { url, headers };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Self-fetch and report the server response time, or why it could not be measured. */
|
|
52
|
+
export async function measureServerResponseTime(
|
|
53
|
+
request: { url: URL; headers: Headers },
|
|
54
|
+
now: () => number = () => performance.now(),
|
|
55
|
+
): Promise<ServerResponseTime | ServerResponseTimeUnmeasured> {
|
|
56
|
+
try {
|
|
57
|
+
const started = now();
|
|
58
|
+
const res = await fetch(request.url, { headers: request.headers, redirect: "manual" });
|
|
59
|
+
const ttfbMs = now() - started;
|
|
60
|
+
await res.body?.cancel();
|
|
61
|
+
const gate = res.headers.get("x-tot-gate");
|
|
62
|
+
if (gate) return { measured: false, reason: `the fetch was answered by the access gate (${gate}), not the store render` };
|
|
63
|
+
if (res.status !== 200) return { measured: false, reason: `the home document answered ${res.status}, not a render` };
|
|
64
|
+
return { measured: true, ...parseServerTiming(res.headers.get("server-timing")), ttfbMs: Math.round(ttfbMs) };
|
|
65
|
+
} catch {
|
|
66
|
+
return { measured: false, reason: "the home document could not be fetched" };
|
|
67
|
+
}
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/storefront-runner",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.4",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
|
|
6
6
|
"packageManager": "pnpm@11.9.0",
|