account for non-object example values in rest docs (#33469)
Co-authored-by: Peter Bengtsson <peterbe@github.com>
This commit is contained in:
@@ -6,6 +6,16 @@ import { useVersion } from 'components/hooks/useVersion'
|
||||
import { useMainContext } from 'components/context/MainContext'
|
||||
|
||||
type CodeExamples = Record<string, any>
|
||||
|
||||
// If the content type is application/x-www-form-urlencoded the format of
|
||||
// the shell example is --data-urlencode param1=value1 --data-urlencode param2=value2
|
||||
// For example, this operation:
|
||||
// https://docs.github.com/en/enterprise/rest/reference/enterprise-admin#enable-or-disable-maintenance-mode
|
||||
const CURL_CONTENT_TYPE_MAPPING: { [key: string]: string } = {
|
||||
'application/x-www-form-urlencoded': '--data-urlencode',
|
||||
'multipart/form-data': '--form',
|
||||
'application/octet-stream': '--data-binary',
|
||||
}
|
||||
/*
|
||||
Generates a curl example
|
||||
|
||||
@@ -19,10 +29,14 @@ type CodeExamples = Record<string, any>
|
||||
export function getShellExample(operation: Operation, codeSample: CodeSample) {
|
||||
const { currentVersion } = useVersion()
|
||||
const { allVersions } = useMainContext()
|
||||
// This allows us to display custom media types like application/sarif+json
|
||||
const defaultAcceptHeader = codeSample?.response?.contentType?.includes('+json')
|
||||
? codeSample.response.contentType
|
||||
: 'application/vnd.github+json'
|
||||
const defaultAcceptHeader = getAcceptHeader(codeSample)
|
||||
|
||||
// For operations that upload data using octet-stream, you need
|
||||
// to explicitly set the content-type header.
|
||||
const contentTypeHeader =
|
||||
codeSample?.request?.contentType === 'application/octet-stream'
|
||||
? '-H "Content-Type: application/octet-stream"'
|
||||
: ''
|
||||
|
||||
let requestPath = codeSample?.request?.parameters
|
||||
? parseTemplate(operation.requestPath).expand(codeSample.request.parameters)
|
||||
@@ -38,22 +52,21 @@ export function getShellExample(operation: Operation, codeSample: CodeSample) {
|
||||
"'\\''"
|
||||
)}'`
|
||||
|
||||
// If the content type is application/x-www-form-urlencoded the format of
|
||||
// the shell example is --data-urlencode param1=value1 --data-urlencode param2=value2
|
||||
// For example, this operation:
|
||||
// https://docs.github.com/en/enterprise/rest/reference/enterprise-admin#enable-or-disable-maintenance-mode
|
||||
|
||||
const CURL_CONTENT_TYPE_MAPPING: { [key: string]: string } = {
|
||||
'application/x-www-form-urlencoded': '--data-urlencode',
|
||||
'multipart/form-data': '--form',
|
||||
}
|
||||
const contentType = codeSample.request.contentType
|
||||
if (codeSample.request.contentType in CURL_CONTENT_TYPE_MAPPING) {
|
||||
if (contentType in CURL_CONTENT_TYPE_MAPPING) {
|
||||
requestBodyParams = ''
|
||||
const paramNames = Object.keys(codeSample.request.bodyParameters)
|
||||
paramNames.forEach((elem) => {
|
||||
requestBodyParams = `${requestBodyParams} ${CURL_CONTENT_TYPE_MAPPING[contentType]} "${elem}=${codeSample.request.bodyParameters[elem]}"`
|
||||
})
|
||||
// Most of the time the example body parameters have a name and value
|
||||
// and are included in an object. But, some cases are a single value
|
||||
// and the type is a string.
|
||||
const { bodyParameters } = codeSample.request
|
||||
if (bodyParameters && typeof bodyParameters === 'object' && !Array.isArray(bodyParameters)) {
|
||||
const paramNames = Object.keys(bodyParameters)
|
||||
paramNames.forEach((elem) => {
|
||||
requestBodyParams = `${requestBodyParams} ${CURL_CONTENT_TYPE_MAPPING[contentType]} "${elem}=${bodyParameters[elem]}"`
|
||||
})
|
||||
} else {
|
||||
requestBodyParams = `${CURL_CONTENT_TYPE_MAPPING[contentType]} "${bodyParameters}"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +84,7 @@ export function getShellExample(operation: Operation, codeSample: CodeSample) {
|
||||
const args = [
|
||||
operation.verb !== 'get' && `-X ${operation.verb.toUpperCase()}`,
|
||||
`-H "Accept: ${defaultAcceptHeader}" \\\n ${authHeader}${apiVersionHeader}`,
|
||||
contentTypeHeader,
|
||||
`${operation.serverUrl}${requestPath}`,
|
||||
requestBodyParams,
|
||||
].filter(Boolean)
|
||||
@@ -88,9 +102,7 @@ export function getShellExample(operation: Operation, codeSample: CodeSample) {
|
||||
-fref,topic-branch=0,payload,{ "deploy": "migrate" }=1,description,Deploy request from hubot=2
|
||||
*/
|
||||
export function getGHExample(operation: Operation, codeSample: CodeSample) {
|
||||
const defaultAcceptHeader = codeSample?.response?.contentType?.includes('+json')
|
||||
? codeSample.response.contentType
|
||||
: 'application/vnd.github+json'
|
||||
const defaultAcceptHeader = getAcceptHeader(codeSample)
|
||||
const hostname = operation.serverUrl !== 'https://api.github.com' ? '--hostname HOSTNAME' : ''
|
||||
|
||||
let requestPath = codeSample?.request?.parameters
|
||||
@@ -101,25 +113,33 @@ export function getGHExample(operation: Operation, codeSample: CodeSample) {
|
||||
requestPath += requiredQueryParams ? `?${requiredQueryParams}` : ''
|
||||
|
||||
let requestBodyParams = ''
|
||||
if (codeSample?.request?.bodyParameters) {
|
||||
const bodyParamValues = Object.values(codeSample.request.bodyParameters)
|
||||
// GitHub CLI does not support sending Objects and arrays using the -F or
|
||||
// -f flags. That support may be added in the future. It is possible to
|
||||
// use gh api --input to take a JSON object from standard input
|
||||
// constructed by jq and piped to gh api. However, we'll hold off on adding
|
||||
// that complexity for now.
|
||||
if (bodyParamValues.some((elem) => typeof elem === 'object')) {
|
||||
return undefined
|
||||
// Most of the time the example body parameters have a name and value
|
||||
// and are included in an object. But, some cases are a single value
|
||||
// and the type is a string.
|
||||
const { bodyParameters } = codeSample.request
|
||||
if (bodyParameters) {
|
||||
if (typeof bodyParameters === 'object' && !Array.isArray(bodyParameters)) {
|
||||
const bodyParamValues = Object.values(codeSample.request.bodyParameters)
|
||||
// GitHub CLI does not support sending Objects and arrays using the -F or
|
||||
// -f flags. That support may be added in the future. It is possible to
|
||||
// use gh api --input to take a JSON object from standard input
|
||||
// constructed by jq and piped to gh api. However, we'll hold off on adding
|
||||
// that complexity for now.
|
||||
if (bodyParamValues.some((elem) => typeof elem === 'object')) {
|
||||
return undefined
|
||||
}
|
||||
requestBodyParams = Object.keys(codeSample.request.bodyParameters)
|
||||
.map((key) => {
|
||||
if (typeof codeSample.request.bodyParameters[key] === 'string') {
|
||||
return `-f ${key}='${codeSample.request.bodyParameters[key]}' `
|
||||
} else {
|
||||
return `-F ${key}=${codeSample.request.bodyParameters[key]} `
|
||||
}
|
||||
})
|
||||
.join('\\\n ')
|
||||
} else {
|
||||
requestBodyParams = `-f '${codeSample.request.bodyParameters}'`
|
||||
}
|
||||
requestBodyParams = Object.keys(codeSample.request.bodyParameters)
|
||||
.map((key) => {
|
||||
if (typeof codeSample.request.bodyParameters[key] === 'string') {
|
||||
return `-f ${key}='${codeSample.request.bodyParameters[key]}' `
|
||||
} else {
|
||||
return `-F ${key}=${codeSample.request.bodyParameters[key]} `
|
||||
}
|
||||
})
|
||||
.join('\\\n ')
|
||||
}
|
||||
const args = [
|
||||
operation.verb !== 'get' && `--method ${operation.verb.toUpperCase()}`,
|
||||
@@ -147,9 +167,21 @@ export function getGHExample(operation: Operation, codeSample: CodeSample) {
|
||||
|
||||
*/
|
||||
export function getJSExample(operation: Operation, codeSample: CodeSample) {
|
||||
const parameters = codeSample.request
|
||||
? { ...codeSample.request.parameters, ...codeSample.request.bodyParameters }
|
||||
: {}
|
||||
const parameters: { [key: string]: string } = {}
|
||||
if (codeSample.request) {
|
||||
Object.assign(parameters, codeSample.request.parameters)
|
||||
// Most of the time the example body parameters have a name and value
|
||||
// and are included in an object. But, some cases are a single value
|
||||
// and the type is a string.
|
||||
if (
|
||||
codeSample.request.bodyParameters &&
|
||||
typeof codeSample.request.bodyParameters !== 'object'
|
||||
) {
|
||||
parameters.data = codeSample.request.bodyParameters
|
||||
} else {
|
||||
Object.assign(parameters, codeSample.request.bodyParameters)
|
||||
}
|
||||
}
|
||||
|
||||
let queryParameters = ''
|
||||
|
||||
@@ -230,3 +262,10 @@ function getRequiredQueryParamsPath(operation: Operation, codeSample: CodeSample
|
||||
|
||||
return requiredQueryParams.toString()
|
||||
}
|
||||
|
||||
function getAcceptHeader(codeSample: CodeSample) {
|
||||
// This allows us to display custom media types like application/sarif+json
|
||||
return codeSample?.response?.contentType?.includes('+json')
|
||||
? codeSample.response.contentType
|
||||
: 'application/vnd.github+json'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user