初始提交: Gitea 项目代码
This commit is contained in:
@@ -0,0 +1,313 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package npm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/modules/util"
|
||||
"gitea.dev/modules/validation"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrInvalidPackage indicates an invalid package
|
||||
ErrInvalidPackage = util.NewInvalidArgumentErrorf("package is invalid")
|
||||
// ErrInvalidPackageName indicates an invalid name
|
||||
ErrInvalidPackageName = util.NewInvalidArgumentErrorf("package name is invalid")
|
||||
// ErrInvalidPackageVersion indicates an invalid version
|
||||
ErrInvalidPackageVersion = util.NewInvalidArgumentErrorf("package version is invalid")
|
||||
// ErrInvalidAttachment indicates a invalid attachment
|
||||
ErrInvalidAttachment = util.NewInvalidArgumentErrorf("package attachment is invalid")
|
||||
// ErrInvalidIntegrity indicates an integrity validation error
|
||||
ErrInvalidIntegrity = util.NewInvalidArgumentErrorf("failed to validate integrity")
|
||||
)
|
||||
|
||||
var nameMatch = regexp.MustCompile(`^(@[a-z0-9-][a-z0-9-._]*/)?[a-z0-9-][a-z0-9-._]*$`)
|
||||
|
||||
// Package represents a npm package
|
||||
type Package struct {
|
||||
Name string
|
||||
Version string
|
||||
DistTags []string
|
||||
Metadata Metadata
|
||||
Filename string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// PackageMetadata https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#package
|
||||
type PackageMetadata struct {
|
||||
ID string `json:"_id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
DistTags map[string]string `json:"dist-tags,omitempty"`
|
||||
Versions map[string]*PackageMetadataVersion `json:"versions"`
|
||||
Readme string `json:"readme,omitempty"`
|
||||
Maintainers []User `json:"maintainers,omitempty"`
|
||||
Time map[string]time.Time `json:"time,omitempty"`
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Repository Repository `json:"repository"`
|
||||
Author User `json:"author"`
|
||||
ReadmeFilename string `json:"readmeFilename,omitempty"`
|
||||
Users map[string]bool `json:"users,omitempty"`
|
||||
License License `json:"license,omitempty"`
|
||||
}
|
||||
|
||||
type License string
|
||||
|
||||
func (l *License) UnmarshalJSON(data []byte) error {
|
||||
switch data[0] {
|
||||
case '"':
|
||||
var value string
|
||||
if err := json.Unmarshal(data, &value); err != nil {
|
||||
return err
|
||||
}
|
||||
*l = License(value)
|
||||
case '{':
|
||||
var values map[string]any
|
||||
if err := json.Unmarshal(data, &values); err != nil {
|
||||
return err
|
||||
}
|
||||
value, _ := values["type"].(string)
|
||||
*l = License(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PackageMetadataVersion documentation: https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#version
|
||||
// PackageMetadataVersion response: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md#abbreviated-version-object
|
||||
type PackageMetadataVersion struct {
|
||||
ID string `json:"_id"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
Author User `json:"author"`
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
License License `json:"license,omitempty"`
|
||||
Repository Repository `json:"repository"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Dependencies map[string]string `json:"dependencies,omitempty"`
|
||||
BundleDependencies []string `json:"bundleDependencies,omitempty"`
|
||||
DevDependencies map[string]string `json:"devDependencies,omitempty"`
|
||||
PeerDependencies map[string]string `json:"peerDependencies,omitempty"`
|
||||
PeerDependenciesMeta map[string]any `json:"peerDependenciesMeta,omitempty"`
|
||||
Bin map[string]string `json:"bin,omitempty"`
|
||||
OptionalDependencies map[string]string `json:"optionalDependencies,omitempty"`
|
||||
Readme string `json:"readme,omitempty"`
|
||||
Dist PackageDistribution `json:"dist"`
|
||||
Maintainers []User `json:"maintainers,omitempty"`
|
||||
}
|
||||
|
||||
// PackageDistribution https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#version
|
||||
type PackageDistribution struct {
|
||||
Integrity string `json:"integrity"`
|
||||
Shasum string `json:"shasum"`
|
||||
Tarball string `json:"tarball"`
|
||||
FileCount int `json:"fileCount,omitempty"`
|
||||
UnpackedSize int `json:"unpackedSize,omitempty"`
|
||||
NpmSignature string `json:"npm-signature,omitempty"`
|
||||
}
|
||||
|
||||
type PackageSearch struct {
|
||||
Objects []*PackageSearchObject `json:"objects"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
type PackageSearchObject struct {
|
||||
Package *PackageSearchPackage `json:"package"`
|
||||
}
|
||||
|
||||
type PackageSearchPackage struct {
|
||||
Scope string `json:"scope"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Date time.Time `json:"date"`
|
||||
Description string `json:"description"`
|
||||
Author User `json:"author"`
|
||||
Publisher User `json:"publisher"`
|
||||
Maintainers []User `json:"maintainers"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Links *PackageSearchPackageLinks `json:"links"`
|
||||
}
|
||||
|
||||
type PackageSearchPackageLinks struct {
|
||||
Registry string `json:"npm"`
|
||||
Homepage string `json:"homepage,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
}
|
||||
|
||||
// User https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#package
|
||||
type User struct {
|
||||
Username string `json:"username,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email,omitempty"`
|
||||
URL string `json:"url,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON is needed because User objects can be strings or objects
|
||||
func (u *User) UnmarshalJSON(data []byte) error {
|
||||
switch data[0] {
|
||||
case '"':
|
||||
if err := json.Unmarshal(data, &u.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
case '{':
|
||||
var tmp struct {
|
||||
Username string `json:"username"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
if err := json.Unmarshal(data, &tmp); err != nil {
|
||||
return err
|
||||
}
|
||||
u.Username = tmp.Username
|
||||
u.Name = tmp.Name
|
||||
u.Email = tmp.Email
|
||||
u.URL = tmp.URL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Repository https://docs.npmjs.com/cli/v11/configuring-npm/package-json#repository
|
||||
type Repository struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
Directory string `json:"directory,omitempty"`
|
||||
}
|
||||
|
||||
// PackageAttachment https://github.com/npm/registry/blob/master/docs/REGISTRY-API.md#package
|
||||
type PackageAttachment struct {
|
||||
ContentType string `json:"content_type"`
|
||||
Data string `json:"data"`
|
||||
Length int `json:"length"`
|
||||
}
|
||||
|
||||
type packageUpload struct {
|
||||
PackageMetadata
|
||||
Attachments map[string]*PackageAttachment `json:"_attachments"`
|
||||
}
|
||||
|
||||
// ParsePackage parses the content into a npm package
|
||||
func ParsePackage(r io.Reader) (*Package, error) {
|
||||
var upload packageUpload
|
||||
if err := json.NewDecoder(r).Decode(&upload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, meta := range upload.Versions {
|
||||
if !validateName(meta.Name) {
|
||||
return nil, ErrInvalidPackageName
|
||||
}
|
||||
|
||||
v, err := version.NewSemver(meta.Version)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidPackageVersion
|
||||
}
|
||||
|
||||
scope := ""
|
||||
name := meta.Name
|
||||
nameParts := strings.SplitN(meta.Name, "/", 2)
|
||||
if len(nameParts) == 2 {
|
||||
scope = nameParts[0]
|
||||
name = nameParts[1]
|
||||
}
|
||||
|
||||
if !validation.IsValidURL(meta.Homepage) {
|
||||
meta.Homepage = ""
|
||||
}
|
||||
|
||||
p := &Package{
|
||||
Name: meta.Name,
|
||||
Version: v.String(),
|
||||
DistTags: make([]string, 0, 1),
|
||||
Metadata: Metadata{
|
||||
Scope: scope,
|
||||
Name: name,
|
||||
Description: meta.Description,
|
||||
Author: meta.Author.Name,
|
||||
License: meta.License,
|
||||
ProjectURL: meta.Homepage,
|
||||
Keywords: meta.Keywords,
|
||||
Dependencies: meta.Dependencies,
|
||||
BundleDependencies: meta.BundleDependencies,
|
||||
DevelopmentDependencies: meta.DevDependencies,
|
||||
PeerDependencies: meta.PeerDependencies,
|
||||
PeerDependenciesMeta: meta.PeerDependenciesMeta,
|
||||
OptionalDependencies: meta.OptionalDependencies,
|
||||
Bin: meta.Bin,
|
||||
Readme: meta.Readme,
|
||||
Repository: meta.Repository,
|
||||
},
|
||||
}
|
||||
|
||||
for tag := range upload.DistTags {
|
||||
p.DistTags = append(p.DistTags, tag)
|
||||
}
|
||||
|
||||
p.Filename = strings.ToLower(fmt.Sprintf("%s-%s.tgz", name, p.Version))
|
||||
|
||||
attachment := func() *PackageAttachment {
|
||||
for _, a := range upload.Attachments {
|
||||
return a
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
if attachment == nil || len(attachment.Data) == 0 {
|
||||
return nil, ErrInvalidAttachment
|
||||
}
|
||||
|
||||
data, err := base64.StdEncoding.DecodeString(attachment.Data)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidAttachment
|
||||
}
|
||||
p.Data = data
|
||||
|
||||
integrity := strings.SplitN(meta.Dist.Integrity, "-", 2)
|
||||
if len(integrity) != 2 {
|
||||
return nil, ErrInvalidIntegrity
|
||||
}
|
||||
integrityHash, err := base64.StdEncoding.DecodeString(integrity[1])
|
||||
if err != nil {
|
||||
return nil, ErrInvalidIntegrity
|
||||
}
|
||||
var hash []byte
|
||||
switch integrity[0] {
|
||||
case "sha1":
|
||||
tmp := sha1.Sum(data)
|
||||
hash = tmp[:]
|
||||
case "sha512":
|
||||
tmp := sha512.Sum512(data)
|
||||
hash = tmp[:]
|
||||
}
|
||||
if !bytes.Equal(integrityHash, hash) {
|
||||
return nil, ErrInvalidIntegrity
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
return nil, ErrInvalidPackage
|
||||
}
|
||||
|
||||
func validateName(name string) bool {
|
||||
if strings.TrimSpace(name) != name {
|
||||
return false
|
||||
}
|
||||
if len(name) == 0 || len(name) > 214 {
|
||||
return false
|
||||
}
|
||||
return nameMatch.MatchString(name)
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package npm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.dev/modules/json"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParsePackage(t *testing.T) {
|
||||
packageScope := "@scope"
|
||||
packageName := "test-package"
|
||||
packageFullName := packageScope + "/" + packageName
|
||||
packageVersion := "1.0.1-pre"
|
||||
packageTag := "latest"
|
||||
packageAuthor := "KN4CK3R"
|
||||
packageBin := "gitea"
|
||||
packageDescription := "Test Description"
|
||||
data := "H4sIAAAAAAAA/ytITM5OTE/VL4DQelnF+XkMVAYGBgZmJiYK2MRBwNDcSIHB2NTMwNDQzMwAqA7IMDUxA9LUdgg2UFpcklgEdAql5kD8ogCnhwio5lJQUMpLzE1VslJQcihOzi9I1S9JLS7RhSYIJR2QgrLUouLM/DyQGkM9Az1D3YIiqExKanFyUWZBCVQ2BKhVwQVJDKwosbQkI78IJO/tZ+LsbRykxFXLNdA+HwWjYBSMgpENACgAbtAACAAA"
|
||||
integrity := "sha512-yA4FJsVhetynGfOC1jFf79BuS+jrHbm0fhh+aHzCQkOaOBXKf9oBnC4a6DnLLnEsHQDRLYd00cwj8sCXpC+wIg=="
|
||||
repository := Repository{
|
||||
Type: "gitea",
|
||||
URL: "http://localhost:3000/gitea/test.git",
|
||||
Directory: "packages/test-package",
|
||||
}
|
||||
|
||||
t.Run("InvalidUpload", func(t *testing.T) {
|
||||
p, err := ParsePackage(bytes.NewReader([]byte{0}))
|
||||
assert.Nil(t, p)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("InvalidUploadNoData", func(t *testing.T) {
|
||||
b, _ := json.Marshal(packageUpload{})
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackage)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageName", func(t *testing.T) {
|
||||
test := func(t *testing.T, name string) {
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: name,
|
||||
Name: name,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageName)
|
||||
}
|
||||
|
||||
test(t, " test ")
|
||||
test(t, " test")
|
||||
test(t, "test ")
|
||||
test(t, "te st")
|
||||
test(t, "Test")
|
||||
test(t, "_test")
|
||||
test(t, ".test")
|
||||
test(t, "^test")
|
||||
test(t, "te^st")
|
||||
test(t, "te|st")
|
||||
test(t, "te)(st")
|
||||
test(t, "te'st")
|
||||
test(t, "te!st")
|
||||
test(t, "te*st")
|
||||
test(t, "te~st")
|
||||
test(t, "invalid/scope")
|
||||
test(t, "@invalid/_name")
|
||||
test(t, "@invalid/.name")
|
||||
})
|
||||
|
||||
t.Run("ValidPackageName", func(t *testing.T) {
|
||||
test := func(t *testing.T, name string) {
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: name,
|
||||
Name: name,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: name,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageVersion)
|
||||
}
|
||||
|
||||
test(t, "test")
|
||||
test(t, "@scope/name")
|
||||
test(t, "@scope/q")
|
||||
test(t, "q")
|
||||
test(t, "@scope/package-name")
|
||||
test(t, "@scope/package.name")
|
||||
test(t, "@scope/package_name")
|
||||
test(t, "123name")
|
||||
test(t, "----")
|
||||
test(t, packageFullName)
|
||||
})
|
||||
|
||||
t.Run("InvalidPackageVersion", func(t *testing.T) {
|
||||
version := "first-version"
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
version: {
|
||||
Name: packageFullName,
|
||||
Version: version,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidPackageVersion)
|
||||
})
|
||||
|
||||
t.Run("InvalidAttachment", func(t *testing.T) {
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
"dummy.tgz": {},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidAttachment)
|
||||
})
|
||||
|
||||
t.Run("InvalidData", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: "/",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidAttachment)
|
||||
})
|
||||
|
||||
t.Run("InvalidIntegrity", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Dist: PackageDistribution{
|
||||
Integrity: "sha512-test==",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidIntegrity)
|
||||
})
|
||||
|
||||
t.Run("InvalidIntegrity2", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Dist: PackageDistribution{
|
||||
Integrity: integrity,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: base64.StdEncoding.EncodeToString([]byte("data")),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.Nil(t, p)
|
||||
assert.ErrorIs(t, err, ErrInvalidIntegrity)
|
||||
})
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
filename := fmt.Sprintf("%s-%s.tgz", packageFullName, packageVersion)
|
||||
b, _ := json.Marshal(packageUpload{
|
||||
PackageMetadata: PackageMetadata{
|
||||
ID: packageFullName,
|
||||
Name: packageFullName,
|
||||
DistTags: map[string]string{
|
||||
packageTag: packageVersion,
|
||||
},
|
||||
Versions: map[string]*PackageMetadataVersion{
|
||||
packageVersion: {
|
||||
Name: packageFullName,
|
||||
Version: packageVersion,
|
||||
Description: packageDescription,
|
||||
Author: User{Name: packageAuthor},
|
||||
License: "MIT",
|
||||
Homepage: "https://gitea.io/",
|
||||
Readme: packageDescription,
|
||||
Dependencies: map[string]string{
|
||||
"package": "1.2.0",
|
||||
},
|
||||
Bin: map[string]string{
|
||||
"bin": packageBin,
|
||||
},
|
||||
Dist: PackageDistribution{
|
||||
Integrity: integrity,
|
||||
},
|
||||
Repository: repository,
|
||||
},
|
||||
},
|
||||
},
|
||||
Attachments: map[string]*PackageAttachment{
|
||||
filename: {
|
||||
Data: data,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
p, err := ParsePackage(bytes.NewReader(b))
|
||||
assert.NotNil(t, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, packageFullName, p.Name)
|
||||
assert.Equal(t, packageVersion, p.Version)
|
||||
assert.Equal(t, []string{packageTag}, p.DistTags)
|
||||
assert.Equal(t, fmt.Sprintf("%s-%s.tgz", strings.Split(packageFullName, "/")[1], packageVersion), p.Filename)
|
||||
b, _ = base64.StdEncoding.DecodeString(data)
|
||||
assert.Equal(t, b, p.Data)
|
||||
assert.Equal(t, packageName, p.Metadata.Name)
|
||||
assert.Equal(t, packageScope, p.Metadata.Scope)
|
||||
assert.Equal(t, packageDescription, p.Metadata.Description)
|
||||
assert.Equal(t, packageDescription, p.Metadata.Readme)
|
||||
assert.Equal(t, packageAuthor, p.Metadata.Author)
|
||||
assert.Equal(t, packageBin, p.Metadata.Bin["bin"])
|
||||
assert.Equal(t, "MIT", string(p.Metadata.License))
|
||||
assert.Equal(t, "https://gitea.io/", p.Metadata.ProjectURL)
|
||||
assert.Contains(t, p.Metadata.Dependencies, "package")
|
||||
assert.Equal(t, "1.2.0", p.Metadata.Dependencies["package"])
|
||||
assert.Equal(t, repository.Type, p.Metadata.Repository.Type)
|
||||
assert.Equal(t, repository.URL, p.Metadata.Repository.URL)
|
||||
assert.Equal(t, repository.Directory, p.Metadata.Repository.Directory)
|
||||
})
|
||||
|
||||
t.Run("ValidLicenseMap", func(t *testing.T) {
|
||||
packageJSON := `{
|
||||
"versions": {
|
||||
"0.1.1": {
|
||||
"name": "dev-null",
|
||||
"version": "0.1.1",
|
||||
"license": {
|
||||
"type": "MIT"
|
||||
},
|
||||
"dist": {
|
||||
"integrity": "sha256-"
|
||||
}
|
||||
}
|
||||
},
|
||||
"_attachments": {
|
||||
"foo": {
|
||||
"data": "AAAA"
|
||||
}
|
||||
}
|
||||
}`
|
||||
p, err := ParsePackage(strings.NewReader(packageJSON))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "MIT", string(p.Metadata.License))
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package npm
|
||||
|
||||
// TagProperty is the name of the property for tag management
|
||||
const TagProperty = "npm.tag"
|
||||
|
||||
// Metadata represents the metadata of a npm package
|
||||
type Metadata struct {
|
||||
Scope string `json:"scope,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Author string `json:"author,omitempty"`
|
||||
License License `json:"license,omitempty"`
|
||||
ProjectURL string `json:"project_url,omitempty"`
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Dependencies map[string]string `json:"dependencies,omitempty"`
|
||||
BundleDependencies []string `json:"bundleDependencies,omitempty"`
|
||||
DevelopmentDependencies map[string]string `json:"development_dependencies,omitempty"`
|
||||
PeerDependencies map[string]string `json:"peer_dependencies,omitempty"`
|
||||
PeerDependenciesMeta map[string]any `json:"peer_dependencies_meta,omitempty"`
|
||||
OptionalDependencies map[string]string `json:"optional_dependencies,omitempty"`
|
||||
Bin map[string]string `json:"bin,omitempty"`
|
||||
Readme string `json:"readme,omitempty"`
|
||||
Repository Repository `json:"repository"`
|
||||
}
|
||||
Reference in New Issue
Block a user