Last active
July 22, 2024 06:33
-
-
Save ChenYFan/8bb67aaced9949e2583492d2956a6f37 to your computer and use it in GitHub Desktop.
使用ServiceWorker,通过下载NPM registry中的tgz包,实现前端下载、UNGZIP、UNTar一条龙分发静态文件
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tarball from "./tarball.js" | |
import { ungzip } from "pako" | |
import CacheDb from "@chenyfan/cache-db" | |
const defaultResponse = `<a href="/?package_name=chenyfan-os&version=0.0.0-r26&path=img%20(4).png">Example</a>` | |
const genTarUrl = (package_name, version) => { | |
//const prefix = "https://registry.npmjs.org/" | |
//const prefix = "https://mirrors.cloud.tencent.com/npm/" | |
//const prefix = "https://registry.npmmirror.com/" | |
//const prefix = "https://mirrors.huaweicloud.com/repository/npm/" //CORS限制 | |
const prefix = "https://npmreg.proxy.ustclug.org/" | |
return prefix + package_name + "/-/" + package_name + "-" + version + ".tgz" | |
} | |
const handleNPMRequest = async (request) => { | |
const url = new URL(request.url) | |
const npm_package = url.searchParams.get("package_name") | |
const npm_version = url.searchParams.get("version") || "latest" | |
const npm_path = url.searchParams.get("path") || "/" | |
if (!npm_package) return new Response(defaultResponse, { status: 400, headers: { "Content-Type": "text/html" } }) | |
const PackageCache = new CacheDb("npmPackage") | |
const ProviderCache = new CacheDb(`npmProvider@${npm_package}@${npm_version}`) | |
let getProviderExist = await ProviderCache.read(`package.json`).then(res => res ? true : false) | |
if (!getProviderExist) { | |
let getPackage = await PackageCache.read(`${npm_package}@${npm_version}`) | |
if (!getPackage) { | |
getPackage = await fetch(genTarUrl(npm_package, npm_version)).then(res => res.arrayBuffer()) | |
await PackageCache.write(`${npm_package}@${npm_version}`, getPackage) | |
} | |
const ungziped = ungzip(new Uint8Array(getPackage)) | |
const ungzipedBlob = new Blob([ungziped], { type: "application/gzip" }) | |
let tarReader = new tarball.TarReader() | |
const unTaredList = await tarReader.readFile(ungzipedBlob) | |
for (let file in unTaredList) { | |
await ProviderCache.write(unTaredList[file].name.replace("package/", ""), tarReader.getFileBinary(unTaredList[file].name)) | |
} | |
} | |
return new Response(await ProviderCache.read(npm_path, { type: "arrayBuffer" }), { | |
status: 200, headers: { | |
"content-type": ((suffix) => { | |
switch (suffix) { | |
case "json": | |
return "application/json" | |
case "js": | |
return "application/javascript" | |
case "css": | |
return "text/css" | |
case "png": | |
return "image/png" | |
case "jpg": | |
return "image/jpeg" | |
case "html": | |
return "text/html" | |
default: | |
return "text/plain" | |
} | |
})(npm_path.split(".").pop().toLowerCase()) | |
} | |
}) | |
} | |
addEventListener("fetch", (event) => { | |
event.respondWith(handleNPMRequest(event.request)) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment