import axios, { AxiosError } from 'axios';
import { parseStringPromise } from 'xml2js';
import { MavenMetadata, MavenCoordinate } from './types.js';
const MAVEN_CENTRAL_BASE = 'https://repo1.maven.org/maven2';
const REQUEST_TIMEOUT = 10000; // 10 seconds
export function parseMavenCoordinate(dependency: string): MavenCoordinate {
const parts = dependency.split(':');
if (parts.length < 2) {
throw new Error(
'Invalid Maven coordinate format. Expected "groupId:artifactId" or "groupId:artifactId:version"'
);
}
return {
groupId: parts[0],
artifactId: parts[1],
version: parts[2],
};
}
export function buildMetadataUrl(coord: MavenCoordinate): string {
// Convert groupId dots to slashes: com.google.guava -> com/google/guava
const groupPath = coord.groupId.replace(/\./g, '/');
return `${MAVEN_CENTRAL_BASE}/${groupPath}/${coord.artifactId}/maven-metadata.xml`;
}
export async function fetchMavenMetadata(
coord: MavenCoordinate
): Promise<MavenMetadata> {
const url = buildMetadataUrl(coord);
try {
const response = await axios.get(url, { timeout: REQUEST_TIMEOUT });
const metadata: MavenMetadata = await parseStringPromise(response.data);
return metadata;
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 404) {
throw new Error(
`Artifact not found: ${coord.groupId}:${coord.artifactId}. ` +
`Verify the groupId and artifactId are correct.`
);
}
throw new Error(`Network error fetching metadata: ${error.message}`);
}
throw error;
}
}
export function extractVersions(metadata: MavenMetadata): string[] {
const versioning = metadata.metadata?.versioning?.[0];
if (!versioning?.versions?.[0]?.version) {
return [];
}
return versioning.versions[0].version;
}