All files / src/lib photo-variants.ts

100% Statements 10/10
100% Branches 6/6
100% Functions 4/4
100% Lines 8/8

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34                    24x           33x           22x   22x 23x 11x 11x     12x      
import { list, del } from "@vercel/blob";
 
/** Deterministic pathname for a persisted resized variant. `version` (a photo's
 *  updatedAt ms) busts the key when the photo changes (e.g. rotation). */
export function variantPath(
  collectionId: string,
  photoId: string,
  width: number,
  version: number,
): string {
  return `variants/${collectionId}/${photoId}/w${width}-v${version}.webp`;
}
 
/** Prefix covering all of a photo's variants (every width + version), or the
 *  whole collection's variants when `photoId` is omitted. */
export function variantPrefix(collectionId: string, photoId?: string): string {
  return photoId ? `variants/${collectionId}/${photoId}/` : `variants/${collectionId}/`;
}
 
/** Best-effort removal of every variant blob under `prefix`. Never throws — a
 *  failure leaves inert, sweepable orphans (mirrors the purge services' del). */
export async function deleteVariants(prefix: string): Promise<void> {
  try {
    let cursor: string | undefined;
    do {
      const res = await list({ prefix, cursor });
      if (res.blobs.length > 0) await del(res.blobs.map((b) => b.url));
      cursor = res.hasMore ? res.cursor : undefined;
    } while (cursor);
  } catch (error) {
    console.error("deleteVariants failed (orphaned, sweepable)", { prefix, error });
  }
}