https://github.com/loic-sharma/nuget-latest-resource
Prototypes the NuGet latest resource
https://github.com/loic-sharma/nuget-latest-resource
Last synced: 3 months ago
JSON representation
Prototypes the NuGet latest resource
- Host: GitHub
- URL: https://github.com/loic-sharma/nuget-latest-resource
- Owner: loic-sharma
- License: mit
- Created: 2021-10-23T06:13:20.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2021-10-23T18:24:26.000Z (over 3 years ago)
- Last Synced: 2025-02-02T12:48:06.421Z (4 months ago)
- Language: C#
- Size: 35.2 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
README
# NuGet V3 latest resource
**Goal**: Speed up Visual Studio's Package Manager UI by prototyping new server APIs! 🚀
Kudos to [@nkolev92](https://github.com/nkolev92) for the idea!
## Background
You can use Visual Studio's Package Manager (PM) UI to browse and install packages. By default, the PM UI displays packages' latest version.
Today the PM UI is powered by [NuGet V3's package metadata API](https://docs.microsoft.com/nuget/api/registration-base-url-resource). This API has a few flaws:
1. It includes the metadata for _all_ versions of a package, not just the latest version.
1. Packages that with more than 128 versions are split across multiple "registration pages"
1. It includes [unlisted versions](https://docs.microsoft.com/en-us/nuget/nuget-org/policies/deleting-packages), which are hidden from the UI.This makes it difficult for Visual Studio to quickly display packages' latest metadata. See:
* [NuGet/Home#8058](https://github.com/NuGet/Home/issues/8058)
* [NuGet/Home#4448](https://github.com/NuGet/Home/issues/4448)### Data
5,510 unique package IDs (~3.4% of total downloads) are affected by registration paging. Here are the top 10 affected packages:
Package Id | Versions | Total downloads
-- | -- | --
xamarin.rgb | 8,442 | 1,004,138
lovecalculator | 8,186 | 877,666
momentum.pm.portalapi | 6,840 | 19,990,722
momentum.pm.api | 6,155 | 4,155,818
namegenerator | 5,415 | 507,700
perseuslibs | 2,985 | 1,674,791
paket | 2,480 | 3,892,159
hilma.common | 2,451 | 204,900
uno.ui | 2,466 | 1,096,205
paket.core | 2,261 | 3,315,729Browsing these packages in Visual Studio's PM UI may result in freezes or crashes.
## Performance results
âš TODO
## Proposed latest API
### Versioning
The following [service index `@type`s](https://docs.microsoft.com/en-us/nuget/api/overview#resources-and-schema) are used:
@type value | Notes
-- | --
Latest/1.0.0 | The initial release### Base URL
The base URL for the following APIs is the value of the `@id` property associated with the aforementioned resource `@type` value. In the following document, the placeholder base URL `{@id}` will be used.
### HTTP methods
All URLs found in the latest resource support the HTTP methods `GET` and `HEAD`.
### Latest versions
Fetch the metadata for a package's latest stable and pre-release versions, excluding unlisted versions.
```
GET {@id}/{LOWER_ID}/latest.json
```#### Request parameters
Name | In | Type | Required | Notes
-- | -- | -- | -- | --
LOWER_ID | URL | string | yes | The package ID, lowercased#### Response
If the package source has no versions of the provided package ID, a 404 status code is returned.
If the package source has one or more versions, including unlisted versions, a 200 status code is returned. The response body is a JSON object with the following properties:
Name | Type | Required | Notes
-- | -- | -- | --
stable | [`catalogEntry` object](https://docs.microsoft.com/nuget/api/registration-base-url-resource#catalog-entry) | No | The metadata for the package's latest stable version, excluding unlisted versions, or `null` if the package does not have any stable versions.
pre-release | [`catalogEntry` object](https://docs.microsoft.com/nuget/api/registration-base-url-resource#catalog-entry) | No | The metadata for the package's latest version, including pre-releases but excluding unlisted versions, or `null` if the package does not have any versions.#### Sample request
```
GET https://loshar001.azureedge.net/latest/fake/latest.json
```#### Sample response
```json
{
"stable": {
"id": "Newtonsoft.Json",
"version": "13.0.1",
...
},
"prerelease": {
"id": "Newtonsoft.Json",
"version": "13.0.1-preview1",
...
}
}
```### Latest stable version
Fetch the metadata for a package's latest stable version, excluding pre-release and unlisted versions.
```
GET {@id}/{LOWER_ID}/latest-stable.json
```#### Request parameters
Name | In | Type | Required | Notes
-- | -- | -- | -- | --
LOWER_ID | URL | string | yes | The package ID, lowercased#### Response
If the package source has no versions of the provided package ID, a 404 status code is returned.
If the package source has one or more versions, including unlisted or pre-release versions, a 200 status code is returned. The response body is a JSON object with the following properties:
Name | Type | Required | Notes
-- | -- | -- | --
stable | [`catalogEntry` object](https://docs.microsoft.com/nuget/api/registration-base-url-resource#catalog-entry) | No | The metadata for the package's latest stable version, excluding pre-release and unlisted versions, or `null` if the package does not have any listed stable versions.#### Sample request
```
GET https://loshar001.azureedge.net/latest/fake/latest-stable.json
```#### Sample response
```json
{
"stable": {
"id": "Newtonsoft.Json",
"version": "13.0.1",
...
}
}
```### Latest, including pre-release versions
Fetch the metadata for a package's latest version, including pre-release versions but excluding unlisted versions.
```
GET {@id}/{LOWER_ID}/latest-prerelease.json
```#### Request parameters
Name | In | Type | Required | Notes
-- | -- | -- | -- | --
LOWER_ID | URL | string | yes | The package ID, lowercased#### Response
If the package source has no versions of the provided package ID, a 404 status code is returned.
If the package source has one or more versions, including unlisted, a 200 status code is returned. The response body is a JSON object with the following properties:
Name | Type | Required | Notes
-- | -- | -- | --
prerelease | [`catalogEntry` object](https://docs.microsoft.com/nuget/api/registration-base-url-resource#catalog-entry) | No | The metadata for the package's latest version, excluding unlisted versions, or `null` if the package does not have any listed versions.#### Sample request
```
GET https://loshar001.azureedge.net/latest/fake/latest-prerelease.json
```#### Sample response
```json
{
"prerelease": {
"id": "Newtonsoft.Json",
"version": "13.0.1-preview1",
...
}
}
```## SDK Sample
The project provides a client SDK to interact with the latest resource:
```cs
using var http = new HttpClient();var clientFactory = new NuGetClientFactory(http, "https://package-source");
var serviceIndexClient = clientFactory.CreateServiceIndexClient();var latestClient = new LatestClient(serviceIndexClient, http);
var latest = await latestClient.GetLatestOrNullAsync("Newtonsoft.Json");Console.WriteLine($"Latest stable version: {latest.Stable.Version}");
Console.WriteLine($"Latest stable description: {latest.Stable.Description}");
```âš Current SDK is a bit hacky. Ideally usage would look like...
```cs
using var http = new HttpClient();var clientFactory = new NuGetClientFactory(http, "https://package-source");
var client = clientFactory.CreateLatestClient();var latest = await latestClient.GetLatestOrNullAsync("Newtonsoft.Json");
Console.WriteLine($"Latest stable version: {latest.Stable.Version}");
Console.WriteLine($"Latest stable description: {latest.Stable.Description}");
```