Skip to content

Commit 2c063eb

Browse files
committed
refactor: remove dead parse() code from git provider adapters
This was refactored at some point long ago to use a shared `parseRepoUrl` but the old unused `parse` methods were orphaned.
1 parent fe95911 commit 2c063eb

1 file changed

Lines changed: 21 additions & 256 deletions

File tree

app/composables/useRepoMeta.ts

Lines changed: 21 additions & 256 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ProviderId, RepoRef } from '#shared/utils/git-providers'
2-
import { GIT_PROVIDER_API_ORIGINS, parseRepoUrl, GITLAB_HOSTS } from '#shared/utils/git-providers'
2+
import { GIT_PROVIDER_API_ORIGINS, parseRepoUrl } from '#shared/utils/git-providers'
33

44
// TTL for git repo metadata (10 minutes - repo stats don't change frequently)
55
const REPO_META_TTL = 60 * 10
@@ -88,8 +88,6 @@ type RadicleProjectResponse = {
8888
}
8989

9090
type ProviderAdapter = {
91-
id: ProviderId
92-
parse(url: URL): RepoRef | null
9391
links(ref: RepoRef): RepoMetaLinks
9492
fetchMeta(
9593
cachedFetch: CachedFetchFunction,
@@ -100,25 +98,6 @@ type ProviderAdapter = {
10098
}
10199

102100
const githubAdapter: ProviderAdapter = {
103-
id: 'github',
104-
105-
parse(url) {
106-
const host = url.hostname.toLowerCase()
107-
if (host !== 'github.com' && host !== 'www.github.com') return null
108-
109-
const parts = url.pathname.split('/').filter(Boolean)
110-
if (parts.length < 2) return null
111-
112-
const owner = decodeURIComponent(parts[0] ?? '').trim()
113-
const repo = decodeURIComponent(parts[1] ?? '')
114-
.trim()
115-
.replace(/\.git$/i, '')
116-
117-
if (!owner || !repo) return null
118-
119-
return { provider: 'github', owner, repo }
120-
},
121-
122101
links(ref) {
123102
const base = `https://github.com/${ref.owner}/${ref.repo}`
124103
return {
@@ -160,30 +139,6 @@ const githubAdapter: ProviderAdapter = {
160139
}
161140

162141
const gitlabAdapter: ProviderAdapter = {
163-
id: 'gitlab',
164-
165-
parse(url) {
166-
const host = url.hostname.toLowerCase()
167-
const isGitLab = GITLAB_HOSTS.some(h => host === h || host === `www.${h}`)
168-
if (!isGitLab) return null
169-
170-
const parts = url.pathname.split('/').filter(Boolean)
171-
if (parts.length < 2) return null
172-
173-
// GitLab supports nested groups, so we join all parts except the last as owner
174-
const repo = decodeURIComponent(parts[parts.length - 1] ?? '')
175-
.trim()
176-
.replace(/\.git$/i, '')
177-
const owner = parts
178-
.slice(0, -1)
179-
.map(p => decodeURIComponent(p).trim())
180-
.join('/')
181-
182-
if (!owner || !repo) return null
183-
184-
return { provider: 'gitlab', owner, repo, host }
185-
},
186-
187142
links(ref) {
188143
const baseHost = ref.host ?? 'gitlab.com'
189144
const base = `https://${baseHost}/${ref.owner}/${ref.repo}`
@@ -224,25 +179,6 @@ const gitlabAdapter: ProviderAdapter = {
224179
}
225180

226181
const bitbucketAdapter: ProviderAdapter = {
227-
id: 'bitbucket',
228-
229-
parse(url) {
230-
const host = url.hostname.toLowerCase()
231-
if (host !== 'bitbucket.org' && host !== 'www.bitbucket.org') return null
232-
233-
const parts = url.pathname.split('/').filter(Boolean)
234-
if (parts.length < 2) return null
235-
236-
const owner = decodeURIComponent(parts[0] ?? '').trim()
237-
const repo = decodeURIComponent(parts[1] ?? '')
238-
.trim()
239-
.replace(/\.git$/i, '')
240-
241-
if (!owner || !repo) return null
242-
243-
return { provider: 'bitbucket', owner, repo }
244-
},
245-
246182
links(ref) {
247183
const base = `https://bitbucket.org/${ref.owner}/${ref.repo}`
248184
return {
@@ -281,25 +217,6 @@ const bitbucketAdapter: ProviderAdapter = {
281217
}
282218

283219
const codebergAdapter: ProviderAdapter = {
284-
id: 'codeberg',
285-
286-
parse(url) {
287-
const host = url.hostname.toLowerCase()
288-
if (host !== 'codeberg.org' && host !== 'www.codeberg.org') return null
289-
290-
const parts = url.pathname.split('/').filter(Boolean)
291-
if (parts.length < 2) return null
292-
293-
const owner = decodeURIComponent(parts[0] ?? '').trim()
294-
const repo = decodeURIComponent(parts[1] ?? '')
295-
.trim()
296-
.replace(/\.git$/i, '')
297-
298-
if (!owner || !repo) return null
299-
300-
return { provider: 'codeberg', owner, repo, host: 'codeberg.org' }
301-
},
302-
303220
links(ref) {
304221
const base = `https://codeberg.org/${ref.owner}/${ref.repo}`
305222
return {
@@ -339,25 +256,6 @@ const codebergAdapter: ProviderAdapter = {
339256
}
340257

341258
const giteeAdapter: ProviderAdapter = {
342-
id: 'gitee',
343-
344-
parse(url) {
345-
const host = url.hostname.toLowerCase()
346-
if (host !== 'gitee.com' && host !== 'www.gitee.com') return null
347-
348-
const parts = url.pathname.split('/').filter(Boolean)
349-
if (parts.length < 2) return null
350-
351-
const owner = decodeURIComponent(parts[0] ?? '').trim()
352-
const repo = decodeURIComponent(parts[1] ?? '')
353-
.trim()
354-
.replace(/\.git$/i, '')
355-
356-
if (!owner || !repo) return null
357-
358-
return { provider: 'gitee', owner, repo }
359-
},
360-
361259
links(ref) {
362260
const base = `https://gitee.com/${ref.owner}/${ref.repo}`
363261
return {
@@ -398,53 +296,8 @@ const giteeAdapter: ProviderAdapter = {
398296

399297
/**
400298
* Generic Gitea adapter for self-hosted instances.
401-
* Matches common Gitea/Forgejo hosting patterns.
402299
*/
403300
const giteaAdapter: ProviderAdapter = {
404-
id: 'gitea',
405-
406-
parse(url) {
407-
const host = url.hostname.toLowerCase()
408-
409-
// Match common Gitea/Forgejo hosting patterns
410-
const giteaPatterns = [
411-
/^git\./i, // git.example.com
412-
/^gitea\./i, // gitea.example.com
413-
/^forgejo\./i, // forgejo.example.com
414-
/^code\./i, // code.example.com
415-
/^src\./i, // src.example.com
416-
/gitea\.io$/i, // *.gitea.io
417-
]
418-
419-
// Skip if it matches other known providers
420-
const skipHosts = [
421-
'github.com',
422-
'gitlab.com',
423-
'codeberg.org',
424-
'bitbucket.org',
425-
'gitee.com',
426-
'sr.ht',
427-
'git.sr.ht',
428-
...GITLAB_HOSTS,
429-
]
430-
if (skipHosts.some(h => host === h || host.endsWith(`.${h}`))) return null
431-
432-
// Check if matches Gitea patterns
433-
if (!giteaPatterns.some(p => p.test(host))) return null
434-
435-
const parts = url.pathname.split('/').filter(Boolean)
436-
if (parts.length < 2) return null
437-
438-
const owner = decodeURIComponent(parts[0] ?? '').trim()
439-
const repo = decodeURIComponent(parts[1] ?? '')
440-
.trim()
441-
.replace(/\.git$/i, '')
442-
443-
if (!owner || !repo) return null
444-
445-
return { provider: 'gitea', owner, repo, host }
446-
},
447-
448301
links(ref) {
449302
const base = `https://${ref.host}/${ref.owner}/${ref.repo}`
450303
return {
@@ -488,27 +341,8 @@ const giteaAdapter: ProviderAdapter = {
488341
}
489342

490343
const sourcehutAdapter: ProviderAdapter = {
491-
id: 'sourcehut',
492-
493-
parse(url) {
494-
const host = url.hostname.toLowerCase()
495-
if (host !== 'sr.ht' && host !== 'git.sr.ht') return null
496-
497-
const parts = url.pathname.split('/').filter(Boolean)
498-
if (parts.length < 2) return null
499-
500-
// Sourcehut uses ~username/repo format
501-
const owner = decodeURIComponent(parts[0] ?? '').trim()
502-
const repo = decodeURIComponent(parts[1] ?? '')
503-
.trim()
504-
.replace(/\.git$/i, '')
505-
506-
if (!owner || !repo) return null
507-
508-
return { provider: 'sourcehut', owner, repo }
509-
},
510-
511344
links(ref) {
345+
// Sourcehut uses ~username/repo format.
512346
const base = `https://git.sr.ht/${ref.owner}/${ref.repo}`
513347
return {
514348
repo: base,
@@ -531,34 +365,8 @@ const sourcehutAdapter: ProviderAdapter = {
531365
}
532366

533367
const tangledAdapter: ProviderAdapter = {
534-
id: 'tangled',
535-
536-
parse(url) {
537-
const host = url.hostname.toLowerCase()
538-
if (
539-
host !== 'tangled.sh' &&
540-
host !== 'www.tangled.sh' &&
541-
host !== 'tangled.org' &&
542-
host !== 'www.tangled.org'
543-
) {
544-
return null
545-
}
546-
547-
const parts = url.pathname.split('/').filter(Boolean)
548-
if (parts.length < 2) return null
549-
550-
// Tangled uses owner/repo format (owner is a domain-like identifier)
551-
const owner = decodeURIComponent(parts[0] ?? '').trim()
552-
const repo = decodeURIComponent(parts[1] ?? '')
553-
.trim()
554-
.replace(/\.git$/i, '')
555-
556-
if (!owner || !repo) return null
557-
558-
return { provider: 'tangled', owner, repo }
559-
},
560-
561368
links(ref) {
369+
// Tangled uses owner/repo format, where owner is a domain-like identifier.
562370
const base = `https://tangled.org/${ref.owner}/${ref.repo}`
563371
return {
564372
repo: base,
@@ -595,24 +403,8 @@ const tangledAdapter: ProviderAdapter = {
595403
}
596404

597405
const radicleAdapter: ProviderAdapter = {
598-
id: 'radicle',
599-
600-
parse(url) {
601-
const host = url.hostname.toLowerCase()
602-
if (host !== 'radicle.at' && host !== 'app.radicle.at' && host !== 'seed.radicle.at') {
603-
return null
604-
}
605-
606-
// Radicle URLs: app.radicle.at/nodes/seed.radicle.at/rad:z3nP4yT1PE3m1PxLEzr173sZtJVnT
607-
const path = url.pathname
608-
const radMatch = path.match(/rad:[a-zA-Z0-9]+/)
609-
if (!radMatch?.[0]) return null
610-
611-
// Use empty owner, store full rad: ID as repo
612-
return { provider: 'radicle', owner: '', repo: radMatch[0], host }
613-
},
614-
615406
links(ref) {
407+
// Radicle refs store the full rad: ID as repo with no owner.
616408
const base = `https://app.radicle.at/nodes/seed.radicle.at/${ref.repo}`
617409
return {
618410
repo: base,
@@ -649,32 +441,10 @@ const radicleAdapter: ProviderAdapter = {
649441
},
650442
}
651443

444+
/**
445+
* Adapter for explicit Forgejo instances.
446+
*/
652447
const forgejoAdapter: ProviderAdapter = {
653-
id: 'forgejo',
654-
655-
parse(url) {
656-
const host = url.hostname.toLowerCase()
657-
658-
// Match explicit Forgejo instances
659-
const forgejoPatterns = [/^forgejo\./i, /\.forgejo\./i]
660-
const knownInstances = ['next.forgejo.org', 'try.next.forgejo.org']
661-
662-
const isMatch = knownInstances.some(h => host === h) || forgejoPatterns.some(p => p.test(host))
663-
if (!isMatch) return null
664-
665-
const parts = url.pathname.split('/').filter(Boolean)
666-
if (parts.length < 2) return null
667-
668-
const owner = decodeURIComponent(parts[0] ?? '').trim()
669-
const repo = decodeURIComponent(parts[1] ?? '')
670-
.trim()
671-
.replace(/\.git$/i, '')
672-
673-
if (!owner || !repo) return null
674-
675-
return { provider: 'forgejo', owner, repo, host }
676-
},
677-
678448
links(ref) {
679449
const base = `https://${ref.host}/${ref.owner}/${ref.repo}`
680450
return {
@@ -715,21 +485,18 @@ const forgejoAdapter: ProviderAdapter = {
715485
},
716486
}
717487

718-
// Order matters: more specific adapters should come before generic ones
719-
const providers: readonly ProviderAdapter[] = [
720-
githubAdapter,
721-
gitlabAdapter,
722-
bitbucketAdapter,
723-
codebergAdapter,
724-
giteeAdapter,
725-
sourcehutAdapter,
726-
tangledAdapter,
727-
radicleAdapter,
728-
forgejoAdapter,
729-
giteaAdapter, // Generic Gitea adapter last as fallback for self-hosted instances
730-
] as const
731-
732-
const parseRepoFromUrl = parseRepoUrl
488+
const providers = {
489+
github: githubAdapter,
490+
gitlab: gitlabAdapter,
491+
bitbucket: bitbucketAdapter,
492+
codeberg: codebergAdapter,
493+
gitee: giteeAdapter,
494+
sourcehut: sourcehutAdapter,
495+
tangled: tangledAdapter,
496+
radicle: radicleAdapter,
497+
forgejo: forgejoAdapter,
498+
gitea: giteaAdapter,
499+
} satisfies Record<ProviderId, ProviderAdapter>
733500

734501
export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | undefined>) {
735502
// Get cachedFetch in setup context (outside async handler)
@@ -738,7 +505,7 @@ export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | unde
738505
const repoRef = computed(() => {
739506
const url = toValue(repositoryUrl)
740507
if (!url) return null
741-
return parseRepoFromUrl(url)
508+
return parseRepoUrl(url)
742509
})
743510

744511
const { data, pending, error, refresh } = useLazyAsyncData<RepoMeta | null>(
@@ -750,9 +517,7 @@ export function useRepoMeta(repositoryUrl: MaybeRefOrGetter<string | null | unde
750517
const ref = repoRef.value
751518
if (!ref) return null
752519

753-
const adapter = providers.find(provider => provider.id === ref.provider)
754-
if (!adapter) return null
755-
520+
const adapter = providers[ref.provider]
756521
const links = adapter.links(ref)
757522
return await adapter.fetchMeta(cachedFetch, ref, links, { signal })
758523
},

0 commit comments

Comments
 (0)