UNPKG

zephyr-agent

Version:
105 lines (104 loc) • 4.23 kB
import "node:module"; import { ZeErrors, ZephyrError } from "../errors/index.mjs"; const STANDARD_DOMAINS = { 'github.com': 'github', 'gitlab.com': 'gitlab', 'bitbucket.org': 'bitbucket', 'dev.azure.com': 'azure', 'ssh.dev.azure.com': 'azure', 'vs-ssh.visualstudio.com': 'azure' }; function getGitProviderInfo(gitUrl) { if (!gitUrl) throw new ZephyrError(ZeErrors.ERR_GIT_REMOTE_ORIGIN); const parsed = parseGitUrl(gitUrl); const resource = parsed.resource.toLowerCase(); const provider = detectProvider(parsed, resource); const isEnterprise = 'custom' === provider; const owner = isEnterprise ? extractEnterpriseOwner(parsed) : extractStandardOwner(parsed, provider); const project = extractProjectName(parsed, provider, isEnterprise); return { provider, owner, project, isEnterprise }; } function parseGitUrl(gitUrl) { let resource; let pathname; if (/^[a-z][a-z\d+.-]*:\/\//i.test(gitUrl)) try { const url = new URL(gitUrl); resource = url.hostname; pathname = url.pathname; } catch { throw new ZephyrError(ZeErrors.ERR_GIT_REMOTE_ORIGIN); } else { const scpRemote = /^(?:[^@/:]+@)?([^/:]+):(.+)$/.exec(gitUrl); if (!scpRemote) throw new ZephyrError(ZeErrors.ERR_GIT_REMOTE_ORIGIN); resource = scpRemote[1]; pathname = scpRemote[2]; } const pathParts = pathname.split('/').filter(Boolean); const name = pathParts.at(-1)?.replace(/\.git$/, '') ?? ''; if (!resource || !name) throw new ZephyrError(ZeErrors.ERR_GIT_REMOTE_ORIGIN); return { resource, owner: pathParts.slice(0, -1).join('/'), name, pathname }; } function detectProvider(parsed, resource) { const standardProvider = STANDARD_DOMAINS[resource]; if (standardProvider) return standardProvider; if (resource.endsWith('.visualstudio.com')) return 'azure'; const pathParts = getPathParts(parsed); if ('v3' === pathParts[0] && pathParts.length >= 4) return 'azure'; return 'custom'; } function extractEnterpriseOwner(parsed) { const domainParts = parsed.resource.split('.'); const baseDomain = domainParts.length > 2 ? domainParts.slice(1).join('.') : parsed.resource; return baseDomain.replace(/\./g, '-').toLowerCase(); } function extractStandardOwner(parsed, provider) { if ('azure' === provider) return extractAzureOrganization(parsed); const rawOwner = parsed.owner.toLowerCase(); if (('gitlab' === provider || 'bitbucket' === provider) && rawOwner.includes('/')) return rawOwner.split('/')[0]; return rawOwner; } function extractProjectName(parsed, provider, isEnterprise) { if ('azure' === provider) return extractAzureRepoName(parsed); if (isEnterprise && 'gitlab' === provider && parsed.pathname) { const pathParts = parsed.pathname.split('/').filter(Boolean); if (pathParts.length > 2) return pathParts[pathParts.length - 1].replace('.git', '').toLowerCase(); } return parsed.name.toLowerCase(); } function extractAzureOrganization(parsed) { const pathParts = getPathParts(parsed); if ('v3' === pathParts[0] && pathParts[1]) return pathParts[1].toLowerCase(); const resource = parsed.resource.toLowerCase(); if (resource.endsWith('.visualstudio.com')) return resource.replace(/\.visualstudio\.com$/, '').toLowerCase(); const organization = pathParts[0]; return (organization || parsed.owner).toLowerCase(); } function extractAzureRepoName(parsed) { const pathParts = getPathParts(parsed); const gitSegmentIndex = pathParts.findIndex((part)=>'_git' === part.toLowerCase()); const repoName = gitSegmentIndex >= 0 ? pathParts[gitSegmentIndex + 1] : pathParts[pathParts.length - 1]; return sanitizeGitName(repoName || parsed.name); } function getPathParts(parsed) { return parsed.pathname.split('/').filter(Boolean); } function sanitizeGitName(name) { try { return decodeURIComponent(name).replace(/\.git$/, '').toLowerCase(); } catch { return name.replace(/\.git$/, '').toLowerCase(); } } export { getGitProviderInfo }; //# sourceMappingURL=git-provider-utils.mjs.map