export function hoistRequestAnnotations()

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}`)
    }
  })
}