diff --git a/services/feedz/feedz.service.js b/services/feedz/feedz.service.js index 54d237de38..9039f1bf9a 100644 --- a/services/feedz/feedz.service.js +++ b/services/feedz/feedz.service.js @@ -7,22 +7,23 @@ import { selectVersion, } from '../nuget/nuget-helpers.js' -const schema = Joi.object({ +const singlePageSchema = Joi.object({ + '@id': Joi.string().required(), items: Joi.array() .items( Joi.object({ - items: Joi.array().items( - Joi.object({ - catalogEntry: Joi.object({ - version: Joi.string().required(), - }).required(), - }) - ), - }).required() + catalogEntry: Joi.object({ + version: Joi.string().required(), + }).required(), + }) ) .default([]), }).required() +const packageSchema = Joi.object({ + items: Joi.array().items(singlePageSchema).default([]), +}).required() + class FeedzVersionService extends BaseJsonService { static category = 'version' @@ -72,7 +73,7 @@ class FeedzVersionService extends BaseJsonService { 'RegistrationsBaseUrl' ) return await this._requestJson({ - schema, + schema: packageSchema, url: `${registrationsBaseUrl}${packageName}/index.json`, errorMessages: { 404: 'repository or package not found', @@ -80,6 +81,25 @@ class FeedzVersionService extends BaseJsonService { }) } + async fetchItems({ json }) { + if (json.items.length === 0 || json.items.some(i => i.catalogEntry)) { + return json + } else { + const items = await Promise.all( + json.items.map(i => + this._requestJson({ + schema: singlePageSchema, + url: i['@id'], + errorMessages: { + 404: 'repository or package not found', + }, + }) + ) + ) + return { items } + } + } + transform({ json, includePrereleases }) { const versions = json.items.flatMap(tl => tl.items.map(i => stripBuildMetadata(i.catalogEntry.version)) @@ -95,7 +115,8 @@ class FeedzVersionService extends BaseJsonService { const includePrereleases = which === 'vpre' const baseUrl = this.apiUrl({ organization, repository }) const json = await this.fetch({ baseUrl, packageName }) - const version = this.transform({ json, includePrereleases }) + const fetchedJson = await this.fetchItems({ json }) + const version = this.transform({ json: fetchedJson, includePrereleases }) return this.constructor.render({ version, feed: FeedzVersionService.defaultBadgeData.label, diff --git a/services/feedz/feedz.tester.js b/services/feedz/feedz.tester.js index 99133e1025..79ecaedb0c 100644 --- a/services/feedz/feedz.tester.js +++ b/services/feedz/feedz.tester.js @@ -11,6 +11,8 @@ export const t = new ServiceTester({ // - Shields.TestPackage: 0.0.1, 0.1.0-pre, 1.0.0 // - Shields.TestPreOnly: 0.1.0-pre // - Shields.MultiPage: 0.1.0-0.1.100 plus 1.0.0 but the response has multiple top-level `items` +// - Shields.MultiPageNoItems: 0.0.0-0.0.256 plus 1.0.0 but the response has multiple top-level +// `items` without `catalogEntries` // The source code of these packages is here: https://github.com/jakubfijalkowski/shields-test-packages // version @@ -46,6 +48,14 @@ t.create('multi-page') color: 'blue', }) +t.create('multi-page-no-items') + .get('/feedz/v/shieldstests/public/Shields.MultiPageNoItems.json') + .expectBadge({ + label: 'feedz', + message: 'v1.0.0', + color: 'blue', + }) + t.create('repository (not found)') .get('/feedz/v/foo/bar/not-a-real-package.json') .expectBadge({ label: 'feedz', message: 'repository or package not found' })