Skip to content

Commit 2e0c04d

Browse files
GustedGusted
authored andcommitted
feat: populate time property for NPM package (#13799)
Of each version we know when it was uploaded, with that information we can populate the `time` property. We're missing two fields (`modified` and `created`) which we can only derive and don't really have a good global state. The problem with deriving, any deletion would no longer be tracker so the created time of a package could change by deleting the oldest version. And modification time would not reflect anything was deleted. Therefore not populating the fields, this looks to be good enough for pnpm as it only relies on these fields if the individual package versions' times are not populated. Resolves forgejo/forgejo#13709 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/13799 Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
1 parent ebb5747 commit 2e0c04d

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

routers/api/packages/npm/api.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Copyright 2026 The Forgejo Authors. All rights reserved.
23
// SPDX-License-Identifier: MIT
34

45
package npm
@@ -8,21 +9,24 @@ import (
89
"encoding/hex"
910
"fmt"
1011
"net/url"
11-
"sort"
12+
"slices"
13+
"time"
1214

1315
packages_model "forgejo.org/models/packages"
1416
npm_module "forgejo.org/modules/packages/npm"
1517
"forgejo.org/modules/setting"
1618
)
1719

1820
func createPackageMetadataResponse(registryURL string, pds []*packages_model.PackageDescriptor) *npm_module.PackageMetadata {
19-
sort.Slice(pds, func(i, j int) bool {
20-
return pds[i].SemVer.LessThan(pds[j].SemVer)
21+
slices.SortFunc(pds, func(a, b *packages_model.PackageDescriptor) int {
22+
return a.SemVer.Compare(b.SemVer)
2123
})
2224

25+
time := make(map[string]time.Time)
2326
versions := make(map[string]*npm_module.PackageMetadataVersion)
2427
distTags := make(map[string]string)
2528
for _, pd := range pds {
29+
time[pd.SemVer.String()] = pd.Version.CreatedUnix.AsTime()
2630
versions[pd.SemVer.String()] = createPackageMetadataVersion(registryURL, pd)
2731

2832
for _, pvp := range pd.VersionProperties {
@@ -42,6 +46,7 @@ func createPackageMetadataResponse(registryURL string, pds []*packages_model.Pac
4246
DistTags: distTags,
4347
Description: metadata.Description,
4448
Readme: metadata.Readme,
49+
Time: time,
4550
Homepage: metadata.ProjectURL,
4651
Author: npm_module.User{Name: metadata.Author},
4752
License: metadata.License,

tests/integration/api_packages_npm_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"net/url"
1111
"strings"
1212
"testing"
13+
"time"
1314

1415
auth_model "forgejo.org/models/auth"
1516
"forgejo.org/models/db"
@@ -19,6 +20,7 @@ import (
1920
user_model "forgejo.org/models/user"
2021
"forgejo.org/modules/packages/npm"
2122
"forgejo.org/modules/setting"
23+
"forgejo.org/modules/timeutil"
2224
"forgejo.org/tests"
2325

2426
"github.com/stretchr/testify/assert"
@@ -90,6 +92,8 @@ func TestPackageNpm(t *testing.T) {
9092

9193
t.Run("Upload", func(t *testing.T) {
9294
defer tests.PrintCurrentTest(t)()
95+
timeutil.MockSet(time.Unix(47176870, 0))
96+
defer timeutil.MockUnset()
9397

9498
req := NewRequestWithBody(t, "PUT", root, strings.NewReader(buildUpload(packageVersion))).
9599
AddTokenAuth(token)
@@ -186,6 +190,9 @@ func TestPackageNpm(t *testing.T) {
186190
assert.Contains(t, result.DistTags, packageTag)
187191
assert.Equal(t, packageVersion, result.DistTags[packageTag])
188192
assert.Equal(t, packageAuthor, result.Author.Name)
193+
if assert.Len(t, result.Time, 1) {
194+
assert.WithinDuration(t, time.Now(), result.Time[packageVersion], time.Minute)
195+
}
189196
assert.Contains(t, result.Versions, packageVersion)
190197
pmv := result.Versions[packageVersion]
191198
assert.Equal(t, fmt.Sprintf("%s@%s", packageName, packageVersion), pmv.ID)

0 commit comments

Comments
 (0)