@void/isr 0.22.0 → 0.23.0

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/core.d.mts CHANGED
@@ -4,7 +4,7 @@
4
4
  * proven safe to share. Readers reject entries from earlier policies instead
5
5
  * of replaying opaque bodies whose private headers were stripped at write time.
6
6
  */
7
- export declare const SHARED_CACHE_POLICY_VERSION: 2;
7
+ export declare const SHARED_CACHE_POLICY_VERSION: 3;
8
8
  export declare const SHARED_CACHE_POLICY_HEADER = "x-void-shared-cache-policy";
9
9
  /** Stamp an internal edge-cache representation with the policy that admitted it. */
10
10
  export declare function markSharedCachePolicy(headers: Headers): void;
package/dist/core.mjs CHANGED
@@ -5,15 +5,15 @@ import { matchLiteralPattern, matchSegmentPattern } from "@void/edge";
5
5
  * proven safe to share. Readers reject entries from earlier policies instead
6
6
  * of replaying opaque bodies whose private headers were stripped at write time.
7
7
  */
8
- const SHARED_CACHE_POLICY_VERSION = 2;
8
+ const SHARED_CACHE_POLICY_VERSION = 3;
9
9
  const SHARED_CACHE_POLICY_HEADER = "x-void-shared-cache-policy";
10
10
  /** Stamp an internal edge-cache representation with the policy that admitted it. */
11
11
  function markSharedCachePolicy(headers) {
12
- headers.set(SHARED_CACHE_POLICY_HEADER, String(2));
12
+ headers.set(SHARED_CACHE_POLICY_HEADER, String(3));
13
13
  }
14
14
  /** Reject opaque edge entries admitted before the current privacy policy. */
15
15
  function hasCurrentSharedCachePolicy(response) {
16
- return response.headers.get(SHARED_CACHE_POLICY_HEADER) === String(2);
16
+ return response.headers.get(SHARED_CACHE_POLICY_HEADER) === String(3);
17
17
  }
18
18
  const PAGE_DATA_SCRIPT_RE = /<script\b[^>]*\bid=(["'])__VOID_PAGE_DATA__\1[^>]*>([\s\S]*?)<\/script>/i;
19
19
  const SKIP_HEADERS = /* @__PURE__ */ new Set([
@@ -89,7 +89,7 @@ function decodeIsrCacheEntry(value, metadata) {
89
89
  const unpacked = unpackIsrValue(value);
90
90
  if (!unpacked) return null;
91
91
  if (!Number.isInteger(metadata.s) || metadata.s < 200 || metadata.s > 599) return null;
92
- if (!Number.isFinite(metadata.c) || metadata.c <= 0 || !Number.isFinite(metadata.t) || metadata.t <= 0 || metadata.p !== 2) return null;
92
+ if (!Number.isFinite(metadata.c) || metadata.c <= 0 || !Number.isFinite(metadata.t) || metadata.t <= 0 || metadata.p !== 3) return null;
93
93
  try {
94
94
  new Headers(unpacked.headers);
95
95
  } catch {
@@ -153,6 +153,10 @@ function isFrameworkDocumentRequest(request) {
153
153
  }
154
154
  /** Return whether a response explicitly forbids storage in a shared cache. */
155
155
  function hasSharedCacheOptOut(response) {
156
+ if (response.headers.get("Vary")?.split(",").some((name) => {
157
+ const header = name.trim().toLowerCase();
158
+ return header !== "" && header !== "x-voidpages";
159
+ })) return true;
156
160
  if (response.headers.has("Set-Cookie")) return true;
157
161
  const cacheControl = response.headers.get("Cache-Control");
158
162
  if (!cacheControl) return false;
package/dist/runtime.mjs CHANGED
@@ -3,6 +3,7 @@ import { SHARED_CACHE_POLICY_HEADER, SHARED_CACHE_POLICY_VERSION, buildVariantOr
3
3
  import { matchSegmentPattern } from "@void/edge";
4
4
  //#region src/runtime.ts
5
5
  const MAX_ISR_VARIANTS_PER_PATH = 200;
6
+ const ISR_STALE_EVICT_GRACE_MS = 864e5;
6
7
  const DIRECT_ISR_PROJECT_ID = "__void_direct__";
7
8
  /** Prefix for the current direct deployment's host-scoped cache entries. */
8
9
  function isrPrefix(deploymentId) {
@@ -91,7 +92,7 @@ async function writeIsrCache(env, host, pathname, response, ttl, variantUrl) {
91
92
  s: status,
92
93
  c: Date.now(),
93
94
  t: ttl,
94
- p: 2
95
+ p: 3
95
96
  } });
96
97
  } catch {}
97
98
  await registerIsrHost(kv, id, host);
@@ -242,12 +243,12 @@ function cloneWithoutVoidPages(request) {
242
243
  * stale, don't retry. An explicit cache opt-out (including `ttl === 0`)
243
244
  * deletes the KV entry and both edge variants.
244
245
  */
245
- async function revalidateInBackground(env, request, host, pathname, defaultTtl, keys, render, variantUrl, htmlOnly) {
246
+ async function revalidateInBackground(env, request, host, pathname, defaultTtl, keys, render, variantUrl, htmlOnly, staleSinceMs) {
246
247
  try {
247
248
  const response = await render(cloneWithoutVoidPages(request));
248
249
  const ttl = resolveRevalidateTtl(response, defaultTtl);
249
250
  const cache = edgeCache();
250
- if (isEventStreamResponse(response)) {
251
+ if (response.status === 200 && isEventStreamResponse(response)) {
251
252
  if (ttl === 0 || hasSharedCacheOptOut(response)) await deleteSharedIsrVariants(env, cache, host, pathname, keys, variantUrl);
252
253
  return;
253
254
  }
@@ -264,7 +265,7 @@ async function revalidateInBackground(env, request, host, pathname, defaultTtl,
264
265
  headers
265
266
  }));
266
267
  await populateJsonEdgeCache(cache, keys.jsonKey, response, ttl, "HIT");
267
- } else if (ttl === 0 || hasSharedCacheOptOut(response) || htmlOnly && !isHtmlResponse(response)) await deleteSharedIsrVariants(env, cache, host, pathname, keys, variantUrl);
268
+ } else if (response.status === 200 && (ttl === 0 || hasSharedCacheOptOut(response) || htmlOnly && !isHtmlResponse(response)) || (response.status === 404 || response.status === 410) && Date.now() - staleSinceMs > ISR_STALE_EVICT_GRACE_MS) await deleteSharedIsrVariants(env, cache, host, pathname, keys, variantUrl);
268
269
  } catch (err) {
269
270
  console.error("ISR revalidation failed:", err);
270
271
  }
@@ -347,7 +348,7 @@ async function handleIsrInternal(request, env, ctx, options, render, htmlOnly) {
347
348
  if (stale) ctx.waitUntil(revalidateInBackground(env, request, host, pathname, isrTtl, {
348
349
  htmlKey,
349
350
  jsonKey
350
- }, render, variantUrl, htmlOnly));
351
+ }, render, variantUrl, htmlOnly, cached.createdAt + cached.ttl * 1e3));
351
352
  const cacheResponse = isrCacheResponse(cached, stale);
352
353
  if (!stale) ctx.waitUntil(safeCachePut(cache, htmlKey, cacheResponse.clone()));
353
354
  return clientRevalidateResponse(cacheResponse);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@void/isr",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/voidzero-dev/void.git",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@cloudflare/workers-types": "^4.20260702.1",
32
- "@void/edge": "0.22.0"
32
+ "@void/edge": "0.23.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "7.0.2",