From 1b91ef57c1a6227b3e525a74a07c1da04da63c53 Mon Sep 17 00:00:00 2001
From: chris48s <chris48s@users.noreply.github.com>
Date: Wed, 24 Jan 2024 20:36:32 +0000
Subject: [PATCH] migrate some services from examples to openApi part 39;
 affects [maven gradle] (#9902)

* allow redirectors to define a openApi property

* migrate some services from examples to openApi

* Update services/gradle-plugin-portal/gradle-plugin-portal.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

* Update services/gradle-plugin-portal/gradle-plugin-portal.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

* Update services/maven-central/maven-central.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

* Update services/maven-central/maven-central.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

* Update services/maven-metadata/maven-metadata.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

* Update services/maven-metadata/maven-metadata.service.js

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>

---------

Co-authored-by: Pierre-Yves Bigourdan <10694593+PyvesB@users.noreply.github.com>
---
 core/base-service/redirector.js               |  4 ++
 core/base-service/service-definitions.js      | 60 ++++++++++---------
 .../gradle-plugin-portal.service.js           | 39 ++++++------
 .../maven-central/maven-central.service.js    | 42 ++++++-------
 services/maven-metadata/maven-metadata.js     |  2 +-
 .../maven-metadata/maven-metadata.service.js  | 40 ++++++++-----
 6 files changed, 107 insertions(+), 80 deletions(-)

diff --git a/core/base-service/redirector.js b/core/base-service/redirector.js
index bac6e5809c5bf..9284907b41e5c 100644
--- a/core/base-service/redirector.js
+++ b/core/base-service/redirector.js
@@ -10,6 +10,7 @@ import {
 import { isValidCategory } from './categories.js'
 import { MetricHelper } from './metric-helper.js'
 import { isValidRoute, prepareRoute, namedParamsForMatch } from './route.js'
+import { openApiSchema } from './service-definitions.js'
 import trace from './trace.js'
 
 const attrSchema = Joi.object({
@@ -18,6 +19,7 @@ const attrSchema = Joi.object({
   isDeprecated: Joi.boolean().default(true),
   route: isValidRoute,
   examples: Joi.array().has(Joi.object()).default([]),
+  openApi: openApiSchema,
   transformPath: Joi.func()
     .maxArity(1)
     .required()
@@ -37,6 +39,7 @@ export default function redirector(attrs) {
     isDeprecated,
     route,
     examples,
+    openApi,
     transformPath,
     transformQueryParams,
     overrideTransformedQueryParams,
@@ -53,6 +56,7 @@ export default function redirector(attrs) {
     static isDeprecated = isDeprecated
     static route = route
     static examples = examples
+    static openApi = openApi
 
     static register({ camp, metricInstance }, { rasterUrl }) {
       const { regex, captureNames } = prepareRoute({
diff --git a/core/base-service/service-definitions.js b/core/base-service/service-definitions.js
index c4beb656361c6..f9aa36615a3db 100644
--- a/core/base-service/service-definitions.js
+++ b/core/base-service/service-definitions.js
@@ -6,6 +6,33 @@ const objectOfKeyValues = Joi.object()
   .pattern(/./, Joi.string().allow(null))
   .required()
 
+const openApiSchema = Joi.object().pattern(
+  /./,
+  Joi.object({
+    get: Joi.object({
+      summary: Joi.string().required(),
+      description: Joi.string(),
+      parameters: Joi.array()
+        .items(
+          Joi.object({
+            name: Joi.string().required(),
+            description: Joi.string(),
+            in: Joi.string().valid('query', 'path').required(),
+            required: Joi.boolean().required(),
+            schema: Joi.object({
+              type: Joi.string().required(),
+              enum: Joi.array(),
+            }).required(),
+            allowEmptyValue: Joi.boolean(),
+            example: Joi.string().allow(null),
+          }),
+        )
+        .min(1)
+        .required(),
+    }).required(),
+  }).required(),
+)
+
 const serviceDefinition = Joi.object({
   category: Joi.string().required(),
   name: Joi.string().required(),
@@ -43,32 +70,7 @@ const serviceDefinition = Joi.object({
       }),
     )
     .default([]),
-  openApi: Joi.object().pattern(
-    /./,
-    Joi.object({
-      get: Joi.object({
-        summary: Joi.string().required(),
-        description: Joi.string(),
-        parameters: Joi.array()
-          .items(
-            Joi.object({
-              name: Joi.string().required(),
-              description: Joi.string(),
-              in: Joi.string().valid('query', 'path').required(),
-              required: Joi.boolean().required(),
-              schema: Joi.object({
-                type: Joi.string().required(),
-                enum: Joi.array(),
-              }).required(),
-              allowEmptyValue: Joi.boolean(),
-              example: Joi.string().allow(null),
-            }),
-          )
-          .min(1)
-          .required(),
-      }).required(),
-    }).required(),
-  ),
+  openApi: openApiSchema,
 }).required()
 
 function assertValidServiceDefinition(service, message = undefined) {
@@ -93,4 +95,8 @@ function assertValidServiceDefinitionExport(examples, message = undefined) {
   Joi.assert(examples, serviceDefinitionExport, message)
 }
 
-export { assertValidServiceDefinition, assertValidServiceDefinitionExport }
+export {
+  assertValidServiceDefinition,
+  assertValidServiceDefinitionExport,
+  openApiSchema,
+}
diff --git a/services/gradle-plugin-portal/gradle-plugin-portal.service.js b/services/gradle-plugin-portal/gradle-plugin-portal.service.js
index 47c23e089800c..12ddb3283e14f 100644
--- a/services/gradle-plugin-portal/gradle-plugin-portal.service.js
+++ b/services/gradle-plugin-portal/gradle-plugin-portal.service.js
@@ -1,5 +1,5 @@
-import { redirector } from '../index.js'
-import { documentation } from '../maven-metadata/maven-metadata.js'
+import { redirector, pathParam, queryParam } from '../index.js'
+import { description } from '../maven-metadata/maven-metadata.js'
 
 export default redirector({
   category: 'version',
@@ -8,24 +8,27 @@ export default redirector({
     base: 'gradle-plugin-portal/v',
     pattern: ':pluginId',
   },
-  examples: [
-    {
-      title: 'Gradle Plugin Portal',
-      queryParams: {
-        versionSuffix: '.1',
-        versionPrefix: '0.10',
+  openApi: {
+    '/gradle-plugin-portal/v/{pluginId}': {
+      get: {
+        summary: 'Gradle Plugin Portal Version',
+        description,
+        parameters: [
+          pathParam({ name: 'pluginId', example: 'com.gradle.plugin-publish' }),
+          queryParam({
+            name: 'versionPrefix',
+            example: '0.10',
+            description: 'Filter only versions with this prefix.',
+          }),
+          queryParam({
+            name: 'versionSuffix',
+            example: '.1',
+            description: 'Filter only versions with this suffix.',
+          }),
+        ],
       },
-      namedParams: {
-        pluginId: 'com.gradle.plugin-publish',
-      },
-      staticPreview: {
-        label: 'plugin portal',
-        message: 'v0.10.1',
-        color: 'blue',
-      },
-      documentation,
     },
-  ],
+  },
   transformPath: () => '/maven-metadata/v',
   transformQueryParams: ({ pluginId }) => {
     const groupPath = pluginId.replace(/\./g, '/')
diff --git a/services/maven-central/maven-central.service.js b/services/maven-central/maven-central.service.js
index 9b8de2451327b..74cefdb8edec5 100644
--- a/services/maven-central/maven-central.service.js
+++ b/services/maven-central/maven-central.service.js
@@ -1,5 +1,5 @@
-import { redirector } from '../index.js'
-import { documentation } from '../maven-metadata/maven-metadata.js'
+import { redirector, pathParam, queryParam } from '../index.js'
+import { description } from '../maven-metadata/maven-metadata.js'
 
 export default redirector({
   category: 'version',
@@ -8,26 +8,28 @@ export default redirector({
     base: 'maven-central/v',
     pattern: ':groupId/:artifactId/:versionPrefix?',
   },
-  examples: [
-    {
-      title: 'Maven Central',
-      pattern: ':groupId/:artifactId',
-      queryParams: {
-        versionSuffix: '-android',
-        versionPrefix: '29',
+  openApi: {
+    '/maven-central/v/{groupId}/{artifactId}': {
+      get: {
+        summary: 'Maven Central Version',
+        description,
+        parameters: [
+          pathParam({ name: 'groupId', example: 'com.google.guava' }),
+          pathParam({ name: 'artifactId', example: 'guava' }),
+          queryParam({
+            name: 'versionPrefix',
+            example: '29',
+            description: 'Filter only versions with this prefix.',
+          }),
+          queryParam({
+            name: 'versionSuffix',
+            example: '-android',
+            description: 'Filter only versions with this suffix.',
+          }),
+        ],
       },
-      namedParams: {
-        groupId: 'com.google.guava',
-        artifactId: 'guava',
-      },
-      staticPreview: {
-        label: 'maven-central',
-        message: 'v29.0-android',
-        color: 'blue',
-      },
-      documentation,
     },
-  ],
+  },
   transformPath: () => '/maven-metadata/v',
   transformQueryParams: ({ groupId, artifactId, versionPrefix }) => {
     const group = encodeURIComponent(groupId).replace(/\./g, '/')
diff --git a/services/maven-metadata/maven-metadata.js b/services/maven-metadata/maven-metadata.js
index b7f9865ea29cb..1220de89367e6 100644
--- a/services/maven-metadata/maven-metadata.js
+++ b/services/maven-metadata/maven-metadata.js
@@ -2,7 +2,7 @@
 
 // the file contains common constants for badges uses maven-metadata
 
-export const documentation = `
+export const description = `
 <p>
 <code>versionPrefix</code> and <code>versionSuffix</code> allow narrowing down
 the range of versions the badge will take into account,
diff --git a/services/maven-metadata/maven-metadata.service.js b/services/maven-metadata/maven-metadata.service.js
index 3bc9cfc089146..d167c068d0f2e 100644
--- a/services/maven-metadata/maven-metadata.service.js
+++ b/services/maven-metadata/maven-metadata.service.js
@@ -1,8 +1,8 @@
 import Joi from 'joi'
 import { optionalUrl } from '../validators.js'
 import { renderVersionBadge } from '../version.js'
-import { BaseXmlService, NotFound } from '../index.js'
-import { documentation } from './maven-metadata.js'
+import { BaseXmlService, NotFound, queryParams } from '../index.js'
+import { description } from './maven-metadata.js'
 
 const queryParamSchema = Joi.object({
   metadataUrl: optionalUrl.required(),
@@ -29,20 +29,32 @@ export default class MavenMetadata extends BaseXmlService {
     queryParamSchema,
   }
 
-  static examples = [
-    {
-      title: 'Maven metadata URL',
-      namedParams: {},
-      queryParams: {
-        metadataUrl:
-          'https://repo1.maven.org/maven2/com/google/guava/guava/maven-metadata.xml',
-        versionPrefix: '29.',
-        versionSuffix: '-android',
+  static openApi = {
+    '/maven-metadata/v': {
+      get: {
+        summary: 'Maven metadata URL',
+        description,
+        parameters: queryParams(
+          {
+            name: 'metadataUrl',
+            example:
+              'https://repo1.maven.org/maven2/com/google/guava/guava/maven-metadata.xml',
+            required: true,
+          },
+          {
+            name: 'versionPrefix',
+            example: '29',
+            description: 'Filter only versions with this prefix.',
+          },
+          {
+            name: 'versionSuffix',
+            example: '-android',
+            description: 'Filter only versions with this suffix.',
+          },
+        ),
       },
-      staticPreview: renderVersionBadge({ version: '29.0-android' }),
-      documentation,
     },
-  ]
+  }
 
   static defaultBadgeData = {
     label: 'maven',