in compiler/src/model/utils.ts [633:721]
export function hoistRequestAnnotations (
request: model.Request, jsDocs: JSDoc[], mappings: Record<string, model.Endpoint>, response: model.TypeName | null
): void {
const knownRequestAnnotations = [
'rest_spec_name', 'behavior', 'class_serializer', 'index_privileges', 'cluster_privileges', 'doc_id', 'availability', 'doc_tag', 'ext_doc_id'
]
// in most of the cases the jsDocs comes in a single block,
// but it can happen that the user defines multiple single line jsDoc.
// We want to enforce a single jsDoc block.
assert(jsDocs, jsDocs.length < 2, 'Use a single multiline jsDoc block instead of multiple single line blocks')
if (jsDocs.length === 1) {
const description = jsDocs[0].getDescription()
if (description.length > 0) request.description = description.trim().replace(/\r/g, '')
}
const tags = parseJsDocTags(jsDocs)
const apiName = tags.rest_spec_name
// TODO (@typescript-eslint/strict-boolean-expressions) is no fun
assert(jsDocs, apiName !== '' && apiName !== null && apiName !== undefined,
`Request ${request.name.name} does not declare the @rest_spec_name to link back to`)
const endpoint = mappings[apiName]
assert(jsDocs, endpoint != null, `The api '${apiName}' does not exists, did you mean '${closest(apiName, Object.keys(mappings))}'?`)
endpoint.request = request.name
endpoint.response = response
// This ensures the tags from request end up on the endpoint
setTags(jsDocs, request, tags, knownRequestAnnotations, (tags, tag, value) => {
if (tag.endsWith('_serializer')) {
} else if (tag === 'rest_spec_name') {
} else if (tag === 'index_privileges') {
const privileges = [
'all', 'auto_configure', 'create', 'create_doc', 'create_index', 'delete', 'delete_index', 'index',
'maintenance', 'manage', 'manage_follow_index', 'manage_ilm', 'manage_leader_index', 'monitor',
'read', 'read_cross_cluster', 'view_index_metadata', 'write'
]
const values = parseCommaSeparated(value)
for (const v of values) {
assert(jsDocs, privileges.includes(v), `The index privilege '${v}' does not exists.`)
}
endpoint.privileges = endpoint.privileges ?? {}
endpoint.privileges.index = values
} else if (tag === 'cluster_privileges') {
const privileges = [
'all', 'cancel_task', 'create_snapshot', 'grant_api_key', 'manage', 'manage_api_key', 'manage_ccr',
'manage_enrich', 'manage_ilm', 'manage_index_templates', 'manage_inference', 'manage_ingest_pipelines', 'manage_logstash_pipelines',
'manage_ml', 'manage_oidc', 'manage_own_api_key', 'manage_pipeline', 'manage_rollup', 'manage_saml', 'manage_search_application', 'manage_search_query_rules', 'manage_search_synonyms',
'manage_security', 'manage_service_account', 'manage_slm', 'manage_token', 'manage_transform', 'manage_user_profile',
'manage_watcher', 'monitor', 'monitor_esql', 'monitor_inference', 'monitor_ml', 'monitor_rollup', 'monitor_snapshot', 'monitor_text_structure',
'monitor_transform', 'monitor_watcher', 'read_ccr', 'read_ilm', 'read_pipeline', 'read_security', 'read_slm', 'transport_client'
]
const values = parseCommaSeparated(value)
for (const v of values) {
assert(jsDocs, privileges.includes(v), `The cluster privilege '${v}' does not exists.`)
}
endpoint.privileges = endpoint.privileges ?? {}
endpoint.privileges.cluster = values
} else if (tag === 'doc_id') {
assert(jsDocs, value.trim() !== '', `Request ${request.name.name}'s @doc_id is cannot be empty`)
endpoint.docId = value.trim()
const docUrl = docIds.find(entry => entry[0] === value.trim())
assert(jsDocs, docUrl != null, `The @doc_id '${value.trim()}' is not present in _doc_ids/table.csv`)
endpoint.docUrl = docUrl[1].replace(/\r/g, '')
} else if (tag === 'ext_doc_id') {
assert(jsDocs, value.trim() !== '', `Request ${request.name.name}'s @ext_doc_id cannot be empty`)
endpoint.extDocId = value.trim()
const docUrl = docIds.find(entry => entry[0] === value.trim())
assert(jsDocs, docUrl != null, `The @ext_doc_id '${value.trim()}' is not present in _doc_ids/table.csv`)
endpoint.extDocUrl = docUrl[1].replace(/\r/g, '')
} else if (tag === 'availability') {
// The @availability jsTag is different than most because it allows
// multiple values within the same docstring, hence needing to parse
// the values again in order to preserve multiple values.
const jsDocsMulti = parseJsDocTagsAllowDuplicates(jsDocs)
const availabilities = parseAvailabilityTags(jsDocs, jsDocsMulti.availability)
// Apply the availabilities to the Endpoint.
for (const [availabilityName, availabilityValue] of Object.entries(availabilities)) {
endpoint.availability[availabilityName] = availabilityValue
}
} else if (tag === 'doc_tag') {
assert(jsDocs, value.trim() !== '', `Request ${request.name.name}'s @doc_tag cannot be empty`)
endpoint.docTag = value.trim()
} else {
assert(jsDocs, false, `Unhandled tag: '${tag}' with value: '${value}' on request ${request.name.name}`)
}
})
}