code.gitea.io/gitea@v1.21.7/routers/api/packages/npm/api.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package npm 5 6 import ( 7 "encoding/base64" 8 "encoding/hex" 9 "fmt" 10 "net/url" 11 "sort" 12 13 packages_model "code.gitea.io/gitea/models/packages" 14 npm_module "code.gitea.io/gitea/modules/packages/npm" 15 ) 16 17 func createPackageMetadataResponse(registryURL string, pds []*packages_model.PackageDescriptor) *npm_module.PackageMetadata { 18 sort.Slice(pds, func(i, j int) bool { 19 return pds[i].SemVer.LessThan(pds[j].SemVer) 20 }) 21 22 versions := make(map[string]*npm_module.PackageMetadataVersion) 23 distTags := make(map[string]string) 24 for _, pd := range pds { 25 versions[pd.SemVer.String()] = createPackageMetadataVersion(registryURL, pd) 26 27 for _, pvp := range pd.VersionProperties { 28 if pvp.Name == npm_module.TagProperty { 29 distTags[pvp.Value] = pd.Version.Version 30 } 31 } 32 } 33 34 latest := pds[len(pds)-1] 35 36 metadata := latest.Metadata.(*npm_module.Metadata) 37 38 return &npm_module.PackageMetadata{ 39 ID: latest.Package.Name, 40 Name: latest.Package.Name, 41 DistTags: distTags, 42 Description: metadata.Description, 43 Readme: metadata.Readme, 44 Homepage: metadata.ProjectURL, 45 Author: npm_module.User{Name: metadata.Author}, 46 License: metadata.License, 47 Versions: versions, 48 Repository: metadata.Repository, 49 } 50 } 51 52 func createPackageMetadataVersion(registryURL string, pd *packages_model.PackageDescriptor) *npm_module.PackageMetadataVersion { 53 hashBytes, _ := hex.DecodeString(pd.Files[0].Blob.HashSHA512) 54 55 metadata := pd.Metadata.(*npm_module.Metadata) 56 57 return &npm_module.PackageMetadataVersion{ 58 ID: fmt.Sprintf("%s@%s", pd.Package.Name, pd.Version.Version), 59 Name: pd.Package.Name, 60 Version: pd.Version.Version, 61 Description: metadata.Description, 62 Author: npm_module.User{Name: metadata.Author}, 63 Homepage: metadata.ProjectURL, 64 License: metadata.License, 65 Dependencies: metadata.Dependencies, 66 DevDependencies: metadata.DevelopmentDependencies, 67 PeerDependencies: metadata.PeerDependencies, 68 OptionalDependencies: metadata.OptionalDependencies, 69 Readme: metadata.Readme, 70 Bin: metadata.Bin, 71 Dist: npm_module.PackageDistribution{ 72 Shasum: pd.Files[0].Blob.HashSHA1, 73 Integrity: "sha512-" + base64.StdEncoding.EncodeToString(hashBytes), 74 Tarball: fmt.Sprintf("%s/%s/-/%s/%s", registryURL, url.QueryEscape(pd.Package.Name), url.PathEscape(pd.Version.Version), url.PathEscape(pd.Files[0].File.LowerName)), 75 }, 76 } 77 } 78 79 func createPackageSearchResponse(pds []*packages_model.PackageDescriptor, total int64) *npm_module.PackageSearch { 80 objects := make([]*npm_module.PackageSearchObject, 0, len(pds)) 81 for _, pd := range pds { 82 metadata := pd.Metadata.(*npm_module.Metadata) 83 84 scope := metadata.Scope 85 if scope == "" { 86 scope = "unscoped" 87 } 88 89 objects = append(objects, &npm_module.PackageSearchObject{ 90 Package: &npm_module.PackageSearchPackage{ 91 Scope: scope, 92 Name: metadata.Name, 93 Version: pd.Version.Version, 94 Date: pd.Version.CreatedUnix.AsLocalTime(), 95 Description: metadata.Description, 96 Author: npm_module.User{Name: metadata.Author}, 97 Publisher: npm_module.User{Name: pd.Owner.Name}, 98 Maintainers: []npm_module.User{}, // npm cli needs this field 99 Keywords: metadata.Keywords, 100 Links: &npm_module.PackageSearchPackageLinks{ 101 Registry: pd.FullWebLink(), 102 Homepage: metadata.ProjectURL, 103 }, 104 }, 105 }) 106 } 107 108 return &npm_module.PackageSearch{ 109 Objects: objects, 110 Total: total, 111 } 112 }