type Tag = { name: string; digest: string; }; class DockerHub { getLatestVersions = async (imageName: string): Promise => { const imagePath = imageName.includes("/") ? imageName : `library/${imageName}`; const tagsResponse = await this.fetch( `/${imagePath}/tags?page_size=10&ordering=last_updated` ).then((res) => res.json()); const tags: Tag[] = tagsResponse.results; if (tags.length === 0) { throw new Error(`No tags found for ${imageName}`); } const latestTag = tags.find((tag) => tag.name === "latest"); if (!latestTag) { return []; } const latestTags = tags .filter((tag) => tag.digest === latestTag.digest) .map((tag) => tag.name); // Example: "1.0.0-alpine" is a variant of "1.0.0" const isVariant = (tag: Tag) => { return latestTags.some((latestTag) => tag.name.includes(latestTag + "-")); }; return latestTags .concat(tags.filter(isVariant).map((tag) => tag.name)) .map((tag) => `${imageName}:${tag}`) .sort(); }; private fetch = async (url: string): Promise => { const fullUrl = `https://hub.docker.com/v2/repositories${url}`; console.debug("-> Docker: Fetching", fullUrl); return fetch(fullUrl); }; } export default DockerHub;