Skip to content

Commit b0eff31

Browse files
committed
use CompressionStream for cache
1 parent 24752f6 commit b0eff31

File tree

6 files changed

+86
-20
lines changed

6 files changed

+86
-20
lines changed

package-lock.json

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

packages/frame/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
"@vitest/coverage-v8": "^0.33.0",
4444
"@vitejs/plugin-react": "^4.0.0",
4545
"@types/markdown-it": "^10.0.3",
46-
"@types/prettier": "^2.6.4"
46+
"@types/prettier": "^2.6.4",
47+
"chai": "^4.3.7"
4748
},
4849
"type": "module",
4950
"source": "src/index.ts",
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import lzstring from "lz-string";
2+
import { compress, decompress } from "./compress";
3+
4+
const SUPPORTS_COMPRESSIONSTREAM = "CompressionStream" in window;
5+
const SEPARATOR = "-=-^-=-";
6+
7+
export class CompressedCache {
8+
constructor(private readonly cacheTimeout: number = 604800000 /* 1 week*/) {}
9+
10+
async getItem(key: string): Promise<string | undefined> {
11+
const cached = localStorage.getItem(key);
12+
if (!cached) {
13+
return undefined;
14+
}
15+
16+
const [dateString, format, text] = cached.split("-=-^-=-");
17+
const cachedDate = new Date(dateString);
18+
const now = new Date();
19+
20+
if (now.getTime() - cachedDate.getTime() > this.cacheTimeout) {
21+
// timed out
22+
return undefined;
23+
}
24+
if (format === "lz") {
25+
return lzstring.decompressFromUTF16(text);
26+
}
27+
28+
if (format === "csgzip" && SUPPORTS_COMPRESSIONSTREAM) {
29+
return (
30+
await decompress(new Blob([text], { type: "text/plain" }))
31+
).text();
32+
}
33+
return undefined;
34+
}
35+
36+
async setItem(key: string, value: string) {
37+
const now = new Date();
38+
39+
let compressed: string;
40+
let format: string;
41+
42+
if (SUPPORTS_COMPRESSIONSTREAM) {
43+
format = "csgzip";
44+
compressed = await (
45+
await compress(new Blob([value], { type: "text/plain" }))
46+
).text();
47+
} else {
48+
format = "lz";
49+
compressed = lzstring.compressToUTF16(value);
50+
}
51+
52+
const cacheContent = `${now.toISOString()}${SEPARATOR}${format}${SEPARATOR}${compressed}`;
53+
localStorage.setItem(key, cacheContent);
54+
}
55+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { expect } from "chai";
2+
import { compress, decompress } from "./compress";
3+
4+
it("compresses / decompressess", async () => {
5+
const str = "hello world ấɖḯƥĭṩčįɳġ ḝłįʈ 🥳";
6+
const compressed = await compress(new Blob([str], { type: "text/plain" }));
7+
const decompressed = await (await decompress(compressed)).text();
8+
expect(decompressed).to.eq(str);
9+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function compress(blob: Blob) {
2+
const compressedReadableStream = blob
3+
.stream()
4+
.pipeThrough(new CompressionStream("deflate"));
5+
return new Response(compressedReadableStream).blob();
6+
}
7+
8+
export async function decompress(blob: Blob) {
9+
const ds = new DecompressionStream("deflate");
10+
const decompressedStream = blob.stream().pipeThrough(ds);
11+
return new Response(decompressedStream).blob();
12+
}

packages/frame/src/runtime/editor/languages/typescript/typeAcquisition.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
/* eslint-disable @typescript-eslint/no-non-null-assertion */
33
// from https://github.com/microsoft/TypeScript-Website/blob/v2/packages/sandbox/src/typeAcquisition.ts
44

5-
import lzstring from "lz-string";
5+
import { CompressedCache } from "./CompressedCache";
66

77
const globalishObj: any =
88
typeof globalThis !== "undefined" ? globalThis : window || {};
99
globalishObj.typeDefinitions = {};
1010

11+
const cache = new CompressedCache();
12+
1113
/**
1214
* Type Defs we've already got, and nulls when something has failed.
1315
* This is to make sure that it doesn't infinite loop.
@@ -408,20 +410,9 @@ const getModuleAndRootDefTypePath = async (
408410
};
409411

410412
const getCachedDTSString = async (config: ATAConfig, url: string) => {
411-
const cached = localStorage.getItem(url);
413+
const cached = await cache.getItem(url);
412414
if (cached) {
413-
const [dateString, text] = cached.split("-=-^-=-");
414-
const cachedDate = new Date(dateString);
415-
const now = new Date();
416-
417-
const cacheTimeout = 604800000; // 1 week
418-
// const cacheTimeout = 60000 // 1 min
419-
420-
if (now.getTime() - cachedDate.getTime() < cacheTimeout) {
421-
return lzstring.decompressFromUTF16(text);
422-
} else {
423-
config.logger.log("Skipping cache for ", url);
424-
}
415+
return cached;
425416
}
426417

427418
const response = await config.fetcher(url);
@@ -448,11 +439,8 @@ const getCachedDTSString = async (config: ATAConfig, url: string) => {
448439
);
449440
}
450441

451-
const now = new Date();
452-
const cacheContent = `${now.toISOString()}-=-^-=-${lzstring.compressToUTF16(
453-
content
454-
)}`;
455-
localStorage.setItem(url, cacheContent);
442+
cache.setItem(url, content);
443+
456444
return content;
457445
};
458446

0 commit comments

Comments
 (0)