repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/ultra/dynamic-artifacts.ts
Rawimport { createHash } from "node:crypto";
import { lstatSync, readdirSync, readFileSync } from "node:fs";
import { basename, join, relative } from "node:path";
export function artifactFiles(root: string): string[] {
const files: string[] = [];
const visit = (dir: string): void => {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const path = join(dir, entry.name);
if (entry.isSymbolicLink()) files.push(path);
else if (entry.isDirectory()) visit(path);
else files.push(path);
}
};
visit(root);
return files;
}
export function hashArtifacts(root: string): string {
const hash = createHash("sha256");
const files = artifactFiles(root)
.filter((path) => basename(path) !== ".ultra-validation.json")
.sort((left, right) =>
relative(root, left)
.replaceAll("\\", "/")
.localeCompare(relative(root, right).replaceAll("\\", "/")),
);
for (const file of files) {
if (lstatSync(file).isSymbolicLink())
throw new Error(`symlink rejected: ${file}`);
const relativePath = relative(root, file).replaceAll("\\", "/");
const bytes = readFileSync(file);
hash.update(String(Buffer.byteLength(relativePath)));
hash.update(":");
hash.update(relativePath);
hash.update(":");
hash.update(String(bytes.length));
hash.update(":");
hash.update(bytes);
}
return hash.digest("hex");
}