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  }