✨ Add Base32 encoding support and enhance caching logic
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
// - https://docs.deno.com/runtime/fundamentals/testing/
|
// - https://docs.deno.com/runtime/fundamentals/testing/
|
||||||
|
|
||||||
import {decodeBase64, encodeBase64} from "jsr:@std/encoding/base64";
|
import {decodeBase64, encodeBase64} from "jsr:@std/encoding/base64";
|
||||||
|
import {encodeBase32} from "jsr:@std/encoding/base32";
|
||||||
import {dirname, fromFileUrl} from "jsr:@std/path";
|
import {dirname, fromFileUrl} from "jsr:@std/path";
|
||||||
import {toArrayBuffer} from "jsr:@std/streams";
|
import {toArrayBuffer} from "jsr:@std/streams";
|
||||||
import {spawn, SpawnOptionsWithoutStdio} from "node:child_process";
|
import {spawn, SpawnOptionsWithoutStdio} from "node:child_process";
|
||||||
@@ -812,12 +813,14 @@ export function joinPath(path1: string, ...paths: string[]): string {
|
|||||||
if (paths != null && paths.length > 0) {
|
if (paths != null && paths.length > 0) {
|
||||||
for (let i = 0; i < paths.length; i++) {
|
for (let i = 0; i < paths.length; i++) {
|
||||||
const path2 = paths[i];
|
const path2 = paths[i];
|
||||||
if (basePath.endsWith("/") && path2.startsWith("/")) {
|
if (path2) {
|
||||||
basePath += path2.substring(1);
|
if (basePath.endsWith("/") && path2.startsWith("/")) {
|
||||||
} else if (basePath.endsWith("/") || path2.startsWith("/")) {
|
basePath += path2.substring(1);
|
||||||
basePath += path2;
|
} else if (basePath.endsWith("/") || path2.startsWith("/")) {
|
||||||
} else {
|
basePath += path2;
|
||||||
basePath += "/" + path2;
|
} else {
|
||||||
|
basePath += "/" + path2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -952,6 +955,10 @@ export function uint8ArrayToHexString(uint8: Uint8Array): string {
|
|||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function uint8ArrayToBase32String(uint8: Unit8Array): string {
|
||||||
|
return encodeBase32(uint8).replaceAll(/=/g, "").toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
export function hexStringToUint8Array(hex: string): Uint8Array {
|
export function hexStringToUint8Array(hex: string): Uint8Array {
|
||||||
hex = hex.trim();
|
hex = hex.trim();
|
||||||
if (hex.startsWith("0x") || hex.startsWith("0X")) {
|
if (hex.startsWith("0x") || hex.startsWith("0X")) {
|
||||||
@@ -1149,6 +1156,12 @@ export async function sha256AndHexOfString(input: string): Promise<string> {
|
|||||||
return uint8ArrayToHexString(new Uint8Array(await sha256OfString(input)));
|
return uint8ArrayToHexString(new Uint8Array(await sha256OfString(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function sha256AndBase32OfString(input: string): Promise<string> {
|
||||||
|
return uint8ArrayToBase32String(
|
||||||
|
new Uint8Array(await sha256OfString(input)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export async function sha256OfString(input: string): Promise<ArrayBuffer> {
|
export async function sha256OfString(input: string): Promise<ArrayBuffer> {
|
||||||
const data = new TextEncoder().encode(input);
|
const data = new TextEncoder().encode(input);
|
||||||
return await crypto.subtle.digest("SHA-256", data);
|
return await crypto.subtle.digest("SHA-256", data);
|
||||||
@@ -1165,6 +1178,8 @@ export interface FetchFileWithCacheMeta {
|
|||||||
|
|
||||||
export interface FetchFileWithCacheOptions {
|
export interface FetchFileWithCacheOptions {
|
||||||
baseDir?: string;
|
baseDir?: string;
|
||||||
|
hierarchicalCacheDir?: boolean;
|
||||||
|
base32Filename?: boolean;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
timeoutMillis?: number;
|
timeoutMillis?: number;
|
||||||
check_cache_file?: (
|
check_cache_file?: (
|
||||||
@@ -1190,9 +1205,13 @@ export async function fetchFileWithCache(
|
|||||||
url: string,
|
url: string,
|
||||||
options?: FetchFileWithCacheOptions,
|
options?: FetchFileWithCacheOptions,
|
||||||
): Promise<FetchFileWithCacheMeta> {
|
): Promise<FetchFileWithCacheMeta> {
|
||||||
const urlSha256 = await sha256AndHexOfString(url);
|
const urlSha256 = options?.base32Filename
|
||||||
|
? await sha256AndBase32OfString(url)
|
||||||
|
: await sha256AndHexOfString(url);
|
||||||
const fileCacheDir = joinPath(
|
const fileCacheDir = joinPath(
|
||||||
resolveFilename(options?.baseDir ?? BASE_FILE_CACHE_DIR),
|
resolveFilename(options?.baseDir ?? BASE_FILE_CACHE_DIR),
|
||||||
|
options?.hierarchicalCacheDir ? urlSha256.substring(0, 2) : null,
|
||||||
|
options?.hierarchicalCacheDir ? urlSha256.substring(2, 4) : null,
|
||||||
urlSha256,
|
urlSha256,
|
||||||
);
|
);
|
||||||
const fileCacheMetaFile = fileCacheDir + ".meta";
|
const fileCacheMetaFile = fileCacheDir + ".meta";
|
||||||
|
|||||||
45
single-scripts/get-rfc.ts
Executable file
45
single-scripts/get-rfc.ts
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env -S deno run -A
|
||||||
|
|
||||||
|
import { parseArgs } from "jsr:@std/cli/parse-args";
|
||||||
|
import {
|
||||||
|
args,
|
||||||
|
exit,
|
||||||
|
fetchFileWithCache,
|
||||||
|
readFileToString,
|
||||||
|
} from "https://global.hatter.ink/script/get/@62/deno-commons-mod.ts";
|
||||||
|
|
||||||
|
const flags = parseArgs(args(), {
|
||||||
|
boolean: ["help"],
|
||||||
|
string: ["id"],
|
||||||
|
});
|
||||||
|
|
||||||
|
function printHelp() {
|
||||||
|
console.log("get-rfc.ts --id <RFC ID>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.help) {
|
||||||
|
printHelp();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags.id) {
|
||||||
|
const rfcId = parseInt(flags.id, 10);
|
||||||
|
if (isNaN(rfcId)) {
|
||||||
|
console.error("Invalid RFC id");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
await getAndPrintRfc(rfcId);
|
||||||
|
} else {
|
||||||
|
printHelp();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAndPrintRfc(rfcId: number): Promise<void> {
|
||||||
|
const url = `https://play.hatter.me/ietf/rfc${rfcId}.txt`;
|
||||||
|
const fileMeta = await fetchFileWithCache(url, {
|
||||||
|
base32Filename: true,
|
||||||
|
hierarchicalCacheDir: true,
|
||||||
|
});
|
||||||
|
const content = await readFileToString(fileMeta.cache_full_path);
|
||||||
|
console.log(content);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user