* Parse URL format into components
(url: string)
| 46 | * Parse URL format into components |
| 47 | */ |
| 48 | function parseUrl(url: string): ParsedSource { |
| 49 | const urlObj = new URL(url); |
| 50 | const host = urlObj.hostname.toLowerCase(); |
| 51 | |
| 52 | let provider: GitProvider; |
| 53 | if (GITHUB_HOSTS.has(host)) { |
| 54 | provider = "github"; |
| 55 | } else if (GITLAB_HOSTS.has(host)) { |
| 56 | provider = "gitlab"; |
| 57 | } else { |
| 58 | throw new Error( |
| 59 | `Unknown Git provider for host: ${host}. Supported providers: ${ALL_GIT_PROVIDERS.join(", ")}`, |
| 60 | ); |
| 61 | } |
| 62 | |
| 63 | // Split by path segments |
| 64 | const segments = urlObj.pathname.split("/").filter(Boolean); |
| 65 | |
| 66 | if (segments.length < 2) { |
| 67 | throw new Error(`Invalid ${provider} URL: ${url}. Expected format: https://${host}/owner/repo`); |
| 68 | } |
| 69 | |
| 70 | const owner = segments[0]; |
| 71 | const repo = segments[1]?.replace(/\.git$/, ""); |
| 72 | |
| 73 | // Check for /tree/ref/path or /blob/ref/path pattern |
| 74 | if (segments.length > 2 && (segments[2] === "tree" || segments[2] === "blob")) { |
| 75 | const ref = segments[3]; |
| 76 | const path = segments.length > 4 ? segments.slice(4).join("/") : undefined; |
| 77 | return { |
| 78 | provider, |
| 79 | owner: owner ?? "", |
| 80 | repo: repo ?? "", |
| 81 | ref, |
| 82 | path, |
| 83 | }; |
| 84 | } |
| 85 | |
| 86 | return { |
| 87 | provider, |
| 88 | owner: owner ?? "", |
| 89 | repo: repo ?? "", |
| 90 | }; |
| 91 | } |
| 92 | |
| 93 | /** |
| 94 | * Parse shorthand format (without provider prefix) |
no test coverage detected
searching dependent graphs…