code.gitea.io/gitea@v1.21.7/routers/api/packages/nuget/api_v3.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package nuget 5 6 import ( 7 "sort" 8 "time" 9 10 packages_model "code.gitea.io/gitea/models/packages" 11 nuget_module "code.gitea.io/gitea/modules/packages/nuget" 12 13 "golang.org/x/text/collate" 14 "golang.org/x/text/language" 15 ) 16 17 // https://docs.microsoft.com/en-us/nuget/api/service-index#resources 18 type ServiceIndexResponseV3 struct { 19 Version string `json:"version"` 20 Resources []ServiceResource `json:"resources"` 21 } 22 23 // https://docs.microsoft.com/en-us/nuget/api/service-index#resource 24 type ServiceResource struct { 25 ID string `json:"@id"` 26 Type string `json:"@type"` 27 } 28 29 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#response 30 type RegistrationIndexResponse struct { 31 RegistrationIndexURL string `json:"@id"` 32 Type []string `json:"@type"` 33 Count int `json:"count"` 34 Pages []*RegistrationIndexPage `json:"items"` 35 } 36 37 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-page-object 38 type RegistrationIndexPage struct { 39 RegistrationPageURL string `json:"@id"` 40 Lower string `json:"lower"` 41 Upper string `json:"upper"` 42 Count int `json:"count"` 43 Items []*RegistrationIndexPageItem `json:"items"` 44 } 45 46 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf-object-in-a-page 47 type RegistrationIndexPageItem struct { 48 RegistrationLeafURL string `json:"@id"` 49 PackageContentURL string `json:"packageContent"` 50 CatalogEntry *CatalogEntry `json:"catalogEntry"` 51 } 52 53 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#catalog-entry 54 type CatalogEntry struct { 55 CatalogLeafURL string `json:"@id"` 56 PackageContentURL string `json:"packageContent"` 57 ID string `json:"id"` 58 Version string `json:"version"` 59 Description string `json:"description"` 60 ReleaseNotes string `json:"releaseNotes"` 61 Authors string `json:"authors"` 62 RequireLicenseAcceptance bool `json:"requireLicenseAcceptance"` 63 ProjectURL string `json:"projectURL"` 64 DependencyGroups []*PackageDependencyGroup `json:"dependencyGroups"` 65 } 66 67 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency-group 68 type PackageDependencyGroup struct { 69 TargetFramework string `json:"targetFramework"` 70 Dependencies []*PackageDependency `json:"dependencies"` 71 } 72 73 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#package-dependency 74 type PackageDependency struct { 75 ID string `json:"id"` 76 Range string `json:"range"` 77 } 78 79 func createRegistrationIndexResponse(l *linkBuilder, pds []*packages_model.PackageDescriptor) *RegistrationIndexResponse { 80 sort.Slice(pds, func(i, j int) bool { 81 return pds[i].SemVer.LessThan(pds[j].SemVer) 82 }) 83 84 items := make([]*RegistrationIndexPageItem, 0, len(pds)) 85 for _, p := range pds { 86 items = append(items, createRegistrationIndexPageItem(l, p)) 87 } 88 89 return &RegistrationIndexResponse{ 90 RegistrationIndexURL: l.GetRegistrationIndexURL(pds[0].Package.Name), 91 Type: []string{"catalog:CatalogRoot", "PackageRegistration", "catalog:Permalink"}, 92 Count: 1, 93 Pages: []*RegistrationIndexPage{ 94 { 95 RegistrationPageURL: l.GetRegistrationIndexURL(pds[0].Package.Name), 96 Count: len(pds), 97 Lower: pds[0].Version.Version, 98 Upper: pds[len(pds)-1].Version.Version, 99 Items: items, 100 }, 101 }, 102 } 103 } 104 105 func createRegistrationIndexPageItem(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationIndexPageItem { 106 metadata := pd.Metadata.(*nuget_module.Metadata) 107 108 return &RegistrationIndexPageItem{ 109 RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), 110 PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version), 111 CatalogEntry: &CatalogEntry{ 112 CatalogLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), 113 PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version), 114 ID: pd.Package.Name, 115 Version: pd.Version.Version, 116 Description: metadata.Description, 117 ReleaseNotes: metadata.ReleaseNotes, 118 Authors: metadata.Authors, 119 ProjectURL: metadata.ProjectURL, 120 DependencyGroups: createDependencyGroups(pd), 121 }, 122 } 123 } 124 125 func createDependencyGroups(pd *packages_model.PackageDescriptor) []*PackageDependencyGroup { 126 metadata := pd.Metadata.(*nuget_module.Metadata) 127 128 dependencyGroups := make([]*PackageDependencyGroup, 0, len(metadata.Dependencies)) 129 for k, v := range metadata.Dependencies { 130 dependencies := make([]*PackageDependency, 0, len(v)) 131 for _, dep := range v { 132 dependencies = append(dependencies, &PackageDependency{ 133 ID: dep.ID, 134 Range: dep.Version, 135 }) 136 } 137 138 dependencyGroups = append(dependencyGroups, &PackageDependencyGroup{ 139 TargetFramework: k, 140 Dependencies: dependencies, 141 }) 142 } 143 return dependencyGroups 144 } 145 146 // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf 147 type RegistrationLeafResponse struct { 148 RegistrationLeafURL string `json:"@id"` 149 Type []string `json:"@type"` 150 Listed bool `json:"listed"` 151 PackageContentURL string `json:"packageContent"` 152 Published time.Time `json:"published"` 153 RegistrationIndexURL string `json:"registration"` 154 } 155 156 func createRegistrationLeafResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *RegistrationLeafResponse { 157 return &RegistrationLeafResponse{ 158 Type: []string{"Package", "http://schema.nuget.org/catalog#Permalink"}, 159 Listed: true, 160 Published: pd.Version.CreatedUnix.AsLocalTime(), 161 RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), 162 PackageContentURL: l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version), 163 RegistrationIndexURL: l.GetRegistrationIndexURL(pd.Package.Name), 164 } 165 } 166 167 // https://docs.microsoft.com/en-us/nuget/api/package-base-address-resource#response 168 type PackageVersionsResponse struct { 169 Versions []string `json:"versions"` 170 } 171 172 func createPackageVersionsResponse(pvs []*packages_model.PackageVersion) *PackageVersionsResponse { 173 versions := make([]string, 0, len(pvs)) 174 for _, pv := range pvs { 175 versions = append(versions, pv.Version) 176 } 177 178 return &PackageVersionsResponse{ 179 Versions: versions, 180 } 181 } 182 183 // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#response 184 type SearchResultResponse struct { 185 TotalHits int64 `json:"totalHits"` 186 Data []*SearchResult `json:"data"` 187 } 188 189 // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result 190 type SearchResult struct { 191 ID string `json:"id"` 192 Version string `json:"version"` 193 Versions []*SearchResultVersion `json:"versions"` 194 Description string `json:"description"` 195 Authors string `json:"authors"` 196 ProjectURL string `json:"projectURL"` 197 RegistrationIndexURL string `json:"registration"` 198 } 199 200 // https://docs.microsoft.com/en-us/nuget/api/search-query-service-resource#search-result 201 type SearchResultVersion struct { 202 RegistrationLeafURL string `json:"@id"` 203 Version string `json:"version"` 204 Downloads int64 `json:"downloads"` 205 } 206 207 func createSearchResultResponse(l *linkBuilder, totalHits int64, pds []*packages_model.PackageDescriptor) *SearchResultResponse { 208 grouped := make(map[string][]*packages_model.PackageDescriptor) 209 for _, pd := range pds { 210 grouped[pd.Package.Name] = append(grouped[pd.Package.Name], pd) 211 } 212 213 keys := make([]string, 0, len(grouped)) 214 for key := range grouped { 215 keys = append(keys, key) 216 } 217 collate.New(language.English, collate.IgnoreCase).SortStrings(keys) 218 219 data := make([]*SearchResult, 0, len(pds)) 220 for _, key := range keys { 221 data = append(data, createSearchResult(l, grouped[key])) 222 } 223 224 return &SearchResultResponse{ 225 TotalHits: totalHits, 226 Data: data, 227 } 228 } 229 230 func createSearchResult(l *linkBuilder, pds []*packages_model.PackageDescriptor) *SearchResult { 231 latest := pds[0] 232 versions := make([]*SearchResultVersion, 0, len(pds)) 233 for _, pd := range pds { 234 if latest.SemVer.LessThan(pd.SemVer) { 235 latest = pd 236 } 237 238 versions = append(versions, &SearchResultVersion{ 239 RegistrationLeafURL: l.GetRegistrationLeafURL(pd.Package.Name, pd.Version.Version), 240 Version: pd.Version.Version, 241 }) 242 } 243 244 metadata := latest.Metadata.(*nuget_module.Metadata) 245 246 return &SearchResult{ 247 ID: latest.Package.Name, 248 Version: latest.Version.Version, 249 Versions: versions, 250 Description: metadata.Description, 251 Authors: metadata.Authors, 252 ProjectURL: metadata.ProjectURL, 253 RegistrationIndexURL: l.GetRegistrationIndexURL(latest.Package.Name), 254 } 255 }