Skip to content

Commit 704de8c

Browse files
committed
Use deno for checks
1 parent 0da730d commit 704de8c

14 files changed

Lines changed: 91 additions & 31 deletions

File tree

.vscode/settings.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"typescript.tsdk": "node_modules/typescript/lib",
3-
"deno.enablePaths": ["packages/cache-handlers/test/deno"],
3+
"deno.enablePaths": [
4+
"packages/cache-handlers/"
5+
],
46
"deno.config": "./deno.json",
57
"deno.suggest.imports.hosts": {
68
"https://deno.land": true,

deno.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cache-handlers/src/invalidation.ts

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,7 @@ export async function invalidateByTag(
6161
// Clean up tag metadata after successful deletion
6262
if (metadataResponse && metadata[validatedTag]) {
6363
delete metadata[validatedTag];
64-
await cache.put(
65-
METADATA_KEY,
66-
new Response(JSON.stringify(metadata), {
67-
headers: { "Content-Type": "application/json" },
68-
}),
69-
);
64+
await cache.put(METADATA_KEY, Response.json(metadata));
7065
}
7166

7267
return deletedCount;
@@ -161,12 +156,7 @@ export async function invalidateByPath(
161156
}
162157
}
163158

164-
await cache.put(
165-
METADATA_KEY,
166-
new Response(JSON.stringify(updatedMetadata), {
167-
headers: { "Content-Type": "application/json" },
168-
}),
169-
);
159+
await cache.put(METADATA_KEY, Response.json(updatedMetadata));
170160
}
171161

172162
return deletedCount;
@@ -336,10 +326,75 @@ export async function getCacheStats(
336326
export async function regenerateCacheStats(
337327
options: InvalidationOptions = {},
338328
): Promise<{ totalEntries: number; entriesByTag: Record<string, number> }> {
339-
// In Deno, we can't enumerate cache keys, so this function cannot work
340-
// without the ability to list all cache entries. Return empty stats.
341-
console.warn(
342-
"regenerateCacheStats: Cannot enumerate cache keys in Deno environment",
343-
);
344-
return { totalEntries: 0, entriesByTag: {} };
329+
const cache = await getCache(options);
330+
interface CacheWithKeys extends Cache {
331+
keys(): Promise<Request[]>;
332+
}
333+
if (!("keys" in cache)) {
334+
console.warn(
335+
"regenerateCacheStats: cache.keys() not supported in this runtime; returning empty stats",
336+
);
337+
return { totalEntries: 0, entriesByTag: {} };
338+
}
339+
340+
let requests: Request[] = [];
341+
try {
342+
requests = await (cache as unknown as CacheWithKeys).keys();
343+
} catch (err) {
344+
console.warn("regenerateCacheStats: failed to enumerate cache keys", err);
345+
return { totalEntries: 0, entriesByTag: {} };
346+
}
347+
348+
const metadata: Record<string, string[]> = {};
349+
const uniqueKeys = new Set<string>();
350+
351+
for (const req of requests) {
352+
const url = req.url;
353+
if (url === METADATA_KEY) {
354+
continue; // skip old metadata entry
355+
}
356+
uniqueKeys.add(url);
357+
358+
let response: Response | undefined;
359+
try {
360+
response = await cache.match(req) as Response | undefined;
361+
} catch {
362+
continue;
363+
}
364+
if (!response) {
365+
continue;
366+
}
367+
const tagHeader = response.headers.get("cache-tag");
368+
if (!tagHeader) {
369+
continue; // cannot reconstruct tags if they were stripped
370+
}
371+
const tags = parseCacheTags(tagHeader);
372+
for (const tag of tags) {
373+
if (!metadata[tag]) {
374+
metadata[tag] = [];
375+
}
376+
metadata[tag].push(url);
377+
}
378+
}
379+
380+
// Write rebuilt metadata (best-effort)
381+
try {
382+
await cache.put(METADATA_KEY, Response.json(metadata));
383+
} catch (err) {
384+
console.warn(
385+
"regenerateCacheStats: failed to persist rebuilt metadata",
386+
err,
387+
);
388+
}
389+
390+
const entriesByTag: Record<string, number> = {};
391+
for (const tag in metadata) {
392+
const list = metadata[tag];
393+
if (!Array.isArray(list)) {
394+
continue;
395+
}
396+
entriesByTag[tag] = list.length;
397+
}
398+
399+
return { totalEntries: uniqueKeys.size, entriesByTag };
345400
}

packages/cache-handlers/src/metadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,6 @@ export async function cleanupVaryMetadata(
238238

239239
return cleanedMetadata;
240240
},
241-
{} as Record<string, any>,
241+
{} as const,
242242
);
243243
}

packages/cache-handlers/src/read.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ export async function readFromCache(
1919
const getCacheKey = config.getCacheKey || defaultGetCacheKey;
2020
const cache = await getCache(config);
2121
const varyMetadataResponse = await cache.match(VARY_METADATA_KEY);
22+
// deno-lint-ignore no-explicit-any
2223
let varyMetadata: Record<string, any> = {};
2324
varyMetadata = await safeJsonParse(
2425
varyMetadataResponse?.clone() || null,
26+
// deno-lint-ignore no-explicit-any
2527
{} as Record<string, any>,
2628
"vary metadata parsing in cache handler",
2729
);

packages/cache-handlers/src/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ export function validateCacheTag(tag: string): string {
575575
}
576576

577577
// Remove ALL control characters (0-31) and DEL (127) except space (32)
578+
// deno-lint-ignore no-control-regex
578579
const sanitized = tag.replace(/[\x00-\x1F\x7F]/g, "").trim();
579580

580581
if (sanitized.length === 0) {

packages/cache-handlers/test/node/conditional.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import {
55
generateETag,
66
parseETag,
77
validateConditionalRequest,
8-
} from "../../src/conditional.js";
9-
import { createCacheHandler } from "../../src/handlers.js";
8+
} from "../../src/conditional.ts";
9+
import { createCacheHandler } from "../../src/handlers.ts";
1010

1111
describe("Conditional Requests - Node.js with undici", () => {
1212
describe("ETag utilities", () => {

packages/cache-handlers/test/node/factory.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { beforeEach, describe, expect, test } from "vitest";
22
import { caches, Request, Response } from "undici";
3-
import { createCacheHandler } from "../../src/index.js";
3+
import { createCacheHandler } from "../../src/index.ts";
44

55
describe("Unified Cache Handler - Node.js with undici", () => {
66
beforeEach(async () => {

packages/cache-handlers/test/node/handlers.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { beforeEach, describe, expect, test } from "vitest";
22
import { caches, Request, Response } from "undici";
3-
import { createCacheHandler } from "../../src/handlers.js";
3+
import { createCacheHandler } from "../../src/handlers.ts";
44

55
describe("Cache Handler - Node.js with undici", () => {
66
beforeEach(async () => {
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// Setup global web APIs using undici's implementations
2+
// @ts-ignore The undici types are wrong
23
import { caches, install } from "undici";
34

45
// Make undici's implementations available globally to match the Web API
56
if (!globalThis.caches) {
6-
globalThis.caches = caches as unknown as CacheStorage;
7+
globalThis.caches = caches as CacheStorage;
78
}
89

910
install();

0 commit comments

Comments
 (0)