docs: add examples and field docs in io module

This commit is contained in:
Andrew Walsh 2026-07-04 11:24:42 -07:00
parent 442edf5a7a
commit 0c9e1dd29d

View file

@ -8,6 +8,16 @@ const FORCE_UPDATE_INCREMENT = "4";
const CACHE_DIRNAME = "cache-apt-pkgs"; const CACHE_DIRNAME = "cache-apt-pkgs";
const CACHE_PREFIX = "cache-apt-pkgs_"; const CACHE_PREFIX = "cache-apt-pkgs_";
/**
* Returns true when apt lists contain at least one reachable file.
*
* This is used as a cheap signal to skip unnecessary apt-get update calls.
*
* @returns True when at least one apt list file is found within the search depth.
*
* @example
* const fresh = isAptListsFresh();
*/
export function isAptListsFresh(): boolean { export function isAptListsFresh(): boolean {
const aptListsPath = "/var/lib/apt/lists"; const aptListsPath = "/var/lib/apt/lists";
const maxDepth = 5; const maxDepth = 5;
@ -40,32 +50,71 @@ export function isAptListsFresh(): boolean {
return search(aptListsPath, 0); return search(aptListsPath, 0);
} }
/**
* Simple package descriptor used by helper code.
*
* @example
* const pkg = new Package("curl", "8.5.0");
* const encoded = pkg.serialize(); // curl@8.5.0
*/
export class Package { export class Package {
constructor( constructor(
/** Package name, for example "curl". */
readonly name: string, readonly name: string,
/** Package version, for example "8.5.0". */
readonly version: string, readonly version: string,
) {} ) {}
/**
* Serializes the package descriptor.
*
* @returns Package serialized as name@version.
*/
serialize(): string { serialize(): string {
return `${this.name}@${this.version}`; return `${this.name}@${this.version}`;
} }
} }
/**
* Structured representation of cache key components.
*
* @example
* const key = new CacheKey("v1", "4", "x86_64", ["curl=8.5.0"]);
*/
export class CacheKey { export class CacheKey {
constructor( constructor(
/** User-provided cache salt/version. */
readonly version: string, readonly version: string,
/** Internal increment used to force broad invalidation. */
readonly forceUpdateIncrement: string, readonly forceUpdateIncrement: string,
/** Architecture string from `arch`. */
readonly arch: string, readonly arch: string,
/** Sorted normalized package specifiers. */
readonly normalizedPackages: string[], readonly normalizedPackages: string[],
) {} ) {}
/**
* Serializes cache key fields to a stable, human-readable format.
*
* @returns Serialized cache key components.
*/
serialize(): string { serialize(): string {
return `${this.version} | ${this.forceUpdateIncrement} | ${this.arch} | ${this.normalizedPackages.join(",")}`; return `${this.version} | ${this.forceUpdateIncrement} | ${this.arch} | ${this.normalizedPackages.join(",")}`;
} }
} }
/**
* Parses a serialized cache key into its component fields.
*
* @param serialized Serialized cache key string.
* @returns Parsed cache key object.
* @throws Error when serialized value does not contain all expected fields.
*
* @example
* const parsed = deserializeCacheKey("v1|4|x86_64|curl=8.5.0");
*/
export function deserializeCacheKey(serialized: string): CacheKey { export function deserializeCacheKey(serialized: string): CacheKey {
const parts = serialized.split("|"); const parts = serialized.split("|").map((part) => part.trim());
if (parts.length !== 4) { if (parts.length !== 4) {
throw new Error(`Invalid serialized cache key: ${serialized}`); throw new Error(`Invalid serialized cache key: ${serialized}`);
} }
@ -75,12 +124,23 @@ export function deserializeCacheKey(serialized: string): CacheKey {
version!, version!,
forceUpdateIncrement!, forceUpdateIncrement!,
arch!, arch!,
normalizedPackagesStr!.split(","), normalizedPackagesStr!
.split(",")
.map((packageSpecifier) => packageSpecifier.trim()),
); );
} }
/**
* Computes action cache path and cache keys for package sets.
*
* @example
* const cacheStore = new Cache("cache-apt-pkgs", commandRunner);
* const key = await cacheStore.getKey(["curl=8.5.0"], "v1");
*/
export class Cache { export class Cache {
/** Absolute cache directory path. */
private readonly cachePath: string; private readonly cachePath: string;
/** Command runner used for architecture detection. */
private readonly commandRunner: CommandRunner; private readonly commandRunner: CommandRunner;
constructor(cacheDir: string = CACHE_DIRNAME, commandRunner: CommandRunner) { constructor(cacheDir: string = CACHE_DIRNAME, commandRunner: CommandRunner) {
@ -88,10 +148,22 @@ export class Cache {
this.commandRunner = commandRunner; this.commandRunner = commandRunner;
} }
/**
* Absolute path to the local cache directory.
*
* @returns Absolute cache directory path.
*/
get path(): string { get path(): string {
return this.cachePath; return this.cachePath;
} }
/**
* Generates the normalized cache key used by GitHub Actions cache.
*
* @param normalizedPackages Sorted package specifiers.
* @param version User-provided cache version salt.
* @returns Cache key with action-specific prefix.
*/
async getKey(normalizedPackages: string[], version: string): Promise<string> { async getKey(normalizedPackages: string[], version: string): Promise<string> {
const architecture = (await this.commandRunner.run("arch")).stdout.trim(); const architecture = (await this.commandRunner.run("arch")).stdout.trim();
let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`; let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`;