package server import ( "html/template" "github.com/git-pkgs/proxy/internal/database" ) // DashboardData contains data for rendering the dashboard. type DashboardData struct { Stats DashboardStats EnrichmentStats EnrichmentStatsView RecentPackages []PackageInfo PopularPackages []PackageInfo } // DashboardStats contains cache statistics for the dashboard. type DashboardStats struct { CachedArtifacts int64 TotalSize string TotalPackages int64 TotalVersions int64 } // EnrichmentStatsView contains enrichment statistics for display. type EnrichmentStatsView struct { EnrichedPackages int64 VulnSyncedPackages int64 TotalVulnerabilities int64 CriticalVulns int64 HighVulns int64 MediumVulns int64 LowVulns int64 HasVulns bool } // PackageInfo contains information about a cached package. type PackageInfo struct { Ecosystem string Name string Version string Size string Hits int64 CachedAt string License string LicenseCategory string VulnCount int64 LatestVersion string IsOutdated bool } // RegistryConfig contains configuration instructions for a package registry. type RegistryConfig struct { ID string Name string Language string Endpoint string Instructions template.HTML } // PackageShowData contains data for rendering the package show page. type PackageShowData struct { Package *database.Package Versions []database.Version Vulnerabilities []database.Vulnerability LicenseCategory string } // VersionShowData contains data for rendering the version show page. type VersionShowData struct { Package *database.Package Version *database.Version Artifacts []database.Artifact Vulnerabilities []database.Vulnerability IsOutdated bool LicenseCategory string HasCachedArtifact bool } // SearchPageData contains data for rendering the search results page. type SearchPageData struct { Query string Ecosystem string Results []SearchResultItem Count int Page int PerPage int TotalPages int } // SearchResultItem represents a single search result for display. type SearchResultItem struct { Ecosystem string Name string LatestVersion string License string LicenseCategory string Hits int64 Size int64 SizeFormatted string CachedAt string VulnCount int64 } // PackagesListPageData contains data for rendering the packages list page. type PackagesListPageData struct { Ecosystem string SortBy string Results []SearchResultItem Count int Page int PerPage int TotalPages int } func supportedEcosystems() []string { // this list should be kept sorted in lexicographic order so // that the 'select' list in the UI will be in the expected // order return []string{ "cargo", "composer", "conan", "conda", "cran", "deb", "gem", "golang", "hex", "maven", "npm", "nuget", "oci", "pub", "pypi", "rpm", } } func ecosystemBadgeLabel(ecosystem string) string { switch ecosystem { case "oci": return "container" case "deb": return "debian" default: return ecosystem } } func ecosystemBadgeClasses(ecosystem string) string { base := "inline-flex items-center px-2 py-0.5 rounded text-xs font-medium" switch ecosystem { case "npm", "maven": return base + " bg-red-100 text-red-700 dark:bg-red-900/50 dark:text-red-300" case "cargo": return base + " bg-orange-100 text-orange-700 dark:bg-orange-900/50 dark:text-orange-300" case "gem": return base + " bg-pink-100 text-pink-700 dark:bg-pink-900/50 dark:text-pink-300" case "go": return base + " bg-cyan-100 text-cyan-700 dark:bg-cyan-900/50 dark:text-cyan-300" case "hex": return base + " bg-purple-100 text-purple-700 dark:bg-purple-900/50 dark:text-purple-300" case "pub": return base + " bg-blue-100 text-blue-700 dark:bg-blue-900/50 dark:text-blue-300" case "pypi": return base + " bg-yellow-100 text-yellow-700 dark:bg-yellow-900/50 dark:text-yellow-300" case "nuget": return base + " bg-indigo-100 text-indigo-700 dark:bg-indigo-900/50 dark:text-indigo-300" case "composer": return base + " bg-violet-100 text-violet-700 dark:bg-violet-900/50 dark:text-violet-300" case "conan": return base + " bg-teal-100 text-teal-700 dark:bg-teal-900/50 dark:text-teal-300" case "conda": return base + " bg-green-100 text-green-700 dark:bg-green-900/50 dark:text-green-300" case "cran": return base + " bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300" case "oci": return base + " bg-sky-100 text-sky-700 dark:bg-sky-900/50 dark:text-sky-300" case "deb": return base + " bg-red-100 text-red-800 dark:bg-red-900/50 dark:text-red-300" case "rpm": return base + " bg-amber-100 text-amber-800 dark:bg-amber-900/50 dark:text-amber-300" default: return base + " bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300" } } func getRegistryConfigs(baseURL string) []RegistryConfig { return []RegistryConfig{ { ID: "npm", Name: "npm", Language: "JavaScript", Endpoint: "/npm/", Instructions: template.HTML(`

Configure npm to use the proxy:

# In ~/.npmrc or project .npmrc
registry=` + baseURL + `/npm/

# Or via environment variable
npm_config_registry=` + baseURL + `/npm/ npm install
`), }, { ID: "cargo", Name: "Cargo", Language: "Rust", Endpoint: "/cargo/", Instructions: template.HTML(`

Configure Cargo to use the proxy (sparse index protocol):

# In ~/.cargo/config.toml or project .cargo/config.toml
[source.crates-io]
replace-with = "proxy"

[source.proxy]
registry = "sparse+` + baseURL + `/cargo/"
`), }, { ID: "gem", Name: "RubyGems", Language: "Ruby", Endpoint: "/gem/", Instructions: template.HTML(`

Configure Bundler/RubyGems to use the proxy:

# In Gemfile
source "` + baseURL + `/gem"

# Or configure globally
gem sources --add ` + baseURL + `/gem/
bundle config mirror.https://rubygems.org ` + baseURL + `/gem
`), }, { ID: "go", Name: "Go Modules", Language: "Go", Endpoint: "/go/", Instructions: template.HTML(`

Set the GOPROXY environment variable:

export GOPROXY=` + baseURL + `/go,direct

# Add to your shell profile for persistence
`), }, { ID: "hex", Name: "Hex", Language: "Elixir", Endpoint: "/hex/", Instructions: template.HTML(`

Configure Hex to use the proxy:

# In ~/.hex/hex.config
{default_url, <<"` + baseURL + `/hex">>}.

# Or via environment variable
export HEX_MIRROR=` + baseURL + `/hex
`), }, { ID: "pub", Name: "pub.dev", Language: "Dart/Flutter", Endpoint: "/pub/", Instructions: template.HTML(`

Set the PUB_HOSTED_URL environment variable:

export PUB_HOSTED_URL=` + baseURL + `/pub
`), }, { ID: "pypi", Name: "PyPI", Language: "Python", Endpoint: "/pypi/", Instructions: template.HTML(`

Configure pip to use the proxy:

# Via command line
pip install --index-url ` + baseURL + `/pypi/simple/ package_name

# In ~/.pip/pip.conf
[global]
index-url = ` + baseURL + `/pypi/simple/
`), }, { ID: "maven", Name: "Maven", Language: "Java", Endpoint: "/maven/", Instructions: template.HTML(`

Configure Maven to use the proxy:

<!-- In ~/.m2/settings.xml -->
<settings>
  <mirrors>
    <mirror>
      <id>proxy</id>
      <mirrorOf>central</mirrorOf>
      <url>` + baseURL + `/maven/</url>
    </mirror>
  </mirrors>
</settings>
`), }, { ID: "nuget", Name: "NuGet", Language: ".NET", Endpoint: "/nuget/", Instructions: template.HTML(`

Configure NuGet to use the proxy:

<!-- In nuget.config -->
<configuration>
  <packageSources>
    <clear />
    <add key="proxy" value="` + baseURL + `/nuget/v3/index.json" />
  </packageSources>
</configuration>

# Or via CLI
dotnet nuget add source ` + baseURL + `/nuget/v3/index.json -n proxy
`), }, { ID: "composer", Name: "Composer", Language: "PHP", Endpoint: "/composer/", Instructions: template.HTML(`

Configure Composer to use the proxy:

// In composer.json
{
    "repositories": [
        {
            "type": "composer",
            "url": "` + baseURL + `/composer"
        }
    ]
}

# Or globally
composer config -g repositories.proxy composer ` + baseURL + `/composer
`), }, { ID: "conan", Name: "Conan", Language: "C/C++", Endpoint: "/conan/", Instructions: template.HTML(`

Configure Conan to use the proxy:

conan remote add proxy ` + baseURL + `/conan
conan remote disable conancenter
`), }, { ID: "conda", Name: "Conda", Language: "Python/R", Endpoint: "/conda/", Instructions: template.HTML(`

Configure Conda to use the proxy:

# In ~/.condarc
channels:
  - ` + baseURL + `/conda/main
  - ` + baseURL + `/conda/conda-forge
default_channels:
  - ` + baseURL + `/conda/main

# Or via command
conda config --add channels ` + baseURL + `/conda/main
`), }, { ID: "cran", Name: "CRAN", Language: "R", Endpoint: "/cran/", Instructions: template.HTML(`

Configure R to use the proxy:

# In R session
options(repos = c(CRAN = "` + baseURL + `/cran"))

# In ~/.Rprofile for persistence
local({
  r <- getOption("repos")
  r["CRAN"] <- "` + baseURL + `/cran"
  options(repos = r)
})
`), }, { ID: "oci", Name: "Container Registry", Language: "Docker/OCI", Endpoint: "/v2/", Instructions: template.HTML(`

Configure Docker to use the proxy as a mirror:

# In /etc/docker/daemon.json
{
  "registry-mirrors": ["` + baseURL + `"]
}

# Then restart Docker
sudo systemctl restart docker

# Or pull directly
docker pull ` + baseURL[8:] + `/library/nginx:latest
`), }, { ID: "deb", Name: "Debian/APT", Language: "Debian/Ubuntu", Endpoint: "/debian/", Instructions: template.HTML(`

Configure APT to use the proxy:

# In /etc/apt/sources.list or /etc/apt/sources.list.d/proxy.list
deb ` + baseURL + `/debian stable main contrib

# Replace your existing sources.list entries with the proxy URL
# Then run:
sudo apt update
`), }, { ID: "rpm", Name: "RPM/Yum", Language: "Fedora/RHEL", Endpoint: "/rpm/", Instructions: template.HTML(`

Configure yum/dnf to use the proxy:

# In /etc/yum.repos.d/proxy.repo
[proxy-fedora]
name=Fedora via Proxy
baseurl=` + baseURL + `/rpm/releases/$releasever/Everything/$basearch/os/
enabled=1
gpgcheck=0

# Then run:
sudo dnf clean all
sudo dnf update
`), }, } }