{"version":3,"sources":["../src/sanitize.ts","../src/compass-api.ts"],"sourcesContent":["// Sanitize text to prevent HTML/markdown injection from untrusted sources.\n// Escapes HTML special characters: & < > \" '\nexport function sanitizeHtml(text: string): string {\n  return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n}\n\n// Sanitize text for safe markdown/MDX embedding: escape HTML special chars and markdown link syntax\nexport function sanitizeMarkdownText(text: string): string {\n  return sanitizeHtml(text).replace(/[[\\]()]/g, (char) => `\\\\${char}`);\n}\n\n// Sanitize URL for safe markdown link embedding: only allow http/https protocols\nexport function sanitizeUrl(url: string): string {\n  try {\n    const parsed = new URL(url);\n    if (parsed.protocol === 'http:' || parsed.protocol === 'https:') {\n      return url.replace(/[()]/g, (char) => encodeURIComponent(char));\n    }\n    return '';\n  } catch {\n    return '';\n  }\n}\n\n// Sanitize IDs to prevent path traversal from untrusted sources\nexport function sanitizeId(id: string): string {\n  return id.replace(/[^a-zA-Z0-9-_]/g, '-');\n}\n","import { CompassConfig } from './compass';\nimport { ApiConfig } from './types';\nimport { sanitizeHtml } from './sanitize';\n\n// Type-level extraction from CompassConfig to avoid importing internal enums\ntype LinkType = NonNullable<CompassConfig['links']>[number]['type'];\ntype FieldType = NonNullable<CompassConfig['fields']>;\ntype CustomFieldType = NonNullable<CompassConfig['customFields']>[number]['type'];\n\n// GraphQL response types — validated against Atlassian Compass API documentation\n// and community examples (see https://community.atlassian.com/forums/Compass-questions/\n// graphql-to-search-for-all-components/qaq-p/2472308)\ntype GraphQLField = {\n  definition: { name: string };\n  value?: string; // via ... on CompassEnumField { value }\n};\n\ntype GraphQLScorecardScore = {\n  scorecardId: string;\n  totalScore: number;\n  maxTotalScore: number;\n};\n\ntype GraphQLComponent = {\n  id: string;\n  name: string;\n  typeId: string;\n  description: string | null;\n  ownerId: string | null;\n  fields: GraphQLField[] | null;\n  links: Array<{\n    type: string;\n    url: string;\n    name: string | null;\n  }> | null;\n  relationships: {\n    nodes?: Array<{\n      relationshipType: string;\n      endNode: { id: string } | null;\n    }>;\n  } | null;\n  labels: Array<{ name: string }> | null;\n  customFields: Array<{\n    definition: { name: string };\n    textValue?: string;\n    booleanValue?: boolean;\n    numberValue?: number;\n  }> | null;\n  scorecardScores: GraphQLScorecardScore[] | null;\n};\n\ntype SearchComponentsResult = {\n  __typename: string;\n  nodes?: Array<{ component: GraphQLComponent }>;\n  pageInfo?: {\n    hasNextPage: boolean;\n    endCursor: string | null;\n  };\n  message?: string;\n  identifier?: string;\n};\n\ntype SearchComponentsResponse = {\n  data?: {\n    compass: {\n      searchComponents: SearchComponentsResult;\n    };\n  };\n  errors?: Array<{ message: string }>;\n};\n\n// Query validated against Compass GraphQL API docs. Key corrections from docs:\n// - Component type field is `typeId` (not `type`)\n// - Labels are objects: `labels { name }` (not plain strings)\n// - Lifecycle/tier use CompassEnumField fragment: `fields { definition { name } ... on CompassEnumField { value } }`\n// - Relationship nodes use `nodeId` (matching creation API input)\nconst SEARCH_COMPONENTS_QUERY = `\n  query searchComponents($cloudId: String!, $after: String) {\n    compass {\n      searchComponents(\n        cloudId: $cloudId\n        query: { after: $after, first: 50 }\n      ) {\n        __typename\n        ... on QueryError { message identifier }\n        ... on CompassSearchComponentConnection {\n          nodes {\n            component {\n              id\n              name\n              typeId\n              description\n              ownerId\n              fields {\n                definition { name }\n                ... on CompassEnumField { value }\n              }\n              links {\n                type\n                url\n                name\n              }\n              relationships {\n                ... on CompassRelationshipConnection {\n                  nodes {\n                    relationshipType\n                    endNode { id }\n                  }\n                }\n              }\n              labels { name }\n              customFields {\n                definition { name }\n                ... on CompassCustomTextField { textValue }\n                ... on CompassCustomBooleanField { booleanValue }\n                ... on CompassCustomNumberField { numberValue }\n              }\n              scorecardScores {\n                scorecardId\n                totalScore\n                maxTotalScore\n              }\n            }\n          }\n          pageInfo {\n            hasNextPage\n            endCursor\n          }\n        }\n      }\n    }\n  }\n`;\n\nconst FETCH_TIMEOUT_MS = 30_000;\n\nexport function resolveValue(value: string): string {\n  if (value.startsWith('$')) {\n    const envVar = value.slice(1);\n    const resolved = process.env[envVar];\n    if (!resolved) throw new Error(`Environment variable ${envVar} is not set`);\n    return resolved;\n  }\n  return value;\n}\n\nfunction buildAuthHeader(email: string, apiToken: string): string {\n  return `Basic ${Buffer.from(`${email}:${apiToken}`).toString('base64')}`;\n}\n\nconst sanitizeText = sanitizeHtml;\n\nfunction mapTier(value: unknown): 1 | 2 | 3 | 4 | undefined {\n  if (value == null) return undefined;\n  // Handle numeric values directly\n  if (typeof value === 'number') {\n    if (value >= 1 && value <= 4) return value as 1 | 2 | 3 | 4;\n    return undefined;\n  }\n  const str = String(value);\n  const match = str.match(/(\\d)/);\n  if (match) {\n    const num = parseInt(match[1], 10);\n    if (num >= 1 && num <= 4) return num as 1 | 2 | 3 | 4;\n  }\n  return undefined;\n}\n\nfunction mapLifecycle(value: unknown): string | undefined {\n  if (value == null) return undefined;\n  const str = String(value);\n  if (!str) return undefined;\n  // API may return uppercase (ACTIVE) or title case (Active) — normalize both\n  const normalized = str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n  const valid: Record<string, string> = {\n    Active: 'Active',\n    'Pre-release': 'Pre-release',\n    Prerelease: 'Pre-release',\n    Deprecated: 'Deprecated',\n  };\n  return valid[normalized] || valid[str];\n}\n\nfunction extractField(fields: GraphQLField[] | null, fieldName: string): string | undefined {\n  if (!fields) return undefined;\n  const field = fields.find((f) => f.definition.name.toLowerCase() === fieldName.toLowerCase());\n  return field?.value || undefined;\n}\n\n// Extract a readable name from a scorecard ARI (e.g., ari:cloud:compass:...:scorecard/.../UUID → UUID).\n// If the value is already a plain name (no colons), return it as-is.\nfunction extractScorecardName(scorecardId: string): string {\n  if (!scorecardId.includes(':')) return scorecardId;\n  const parts = scorecardId.split('/');\n  return parts[parts.length - 1] || scorecardId;\n}\n\nfunction mapComponent(component: GraphQLComponent, scorecardNames?: Map<string, string>): CompassConfig {\n  const config: CompassConfig = {\n    name: component.name,\n    id: component.id,\n    description: component.description || undefined,\n    typeId: component.typeId as CompassConfig['typeId'],\n  };\n\n  if (component.ownerId) {\n    config.ownerId = component.ownerId;\n  }\n\n  const lifecycle = mapLifecycle(extractField(component.fields, 'lifecycle'));\n  const tier = mapTier(extractField(component.fields, 'tier'));\n  if (lifecycle || tier) {\n    config.fields = { lifecycle: lifecycle as FieldType['lifecycle'], tier };\n  }\n\n  if (component.links && component.links.length > 0) {\n    config.links = component.links.map((link) => ({\n      type: link.type as LinkType,\n      url: link.url,\n      name: link.name || undefined,\n    }));\n  }\n\n  if (component.relationships?.nodes && component.relationships.nodes.length > 0) {\n    const dependsOn = component.relationships.nodes\n      .filter((r) => r.relationshipType === 'DEPENDS_ON' && r.endNode?.id)\n      .map((r) => r.endNode!.id);\n    if (dependsOn.length > 0) {\n      config.relationships = { DEPENDS_ON: dependsOn };\n    }\n  }\n\n  if (component.labels && component.labels.length > 0) {\n    config.labels = component.labels.map((l) => l.name);\n  }\n\n  if (component.customFields && component.customFields.length > 0) {\n    config.customFields = component.customFields.map((cf) => {\n      // Infer type from which value field is populated (API doesn't expose type on definition)\n      let type: CustomFieldType = 'text' as CustomFieldType;\n      if (cf.booleanValue !== undefined && cf.booleanValue !== null) type = 'boolean' as CustomFieldType;\n      else if (cf.numberValue !== undefined && cf.numberValue !== null) type = 'number' as CustomFieldType;\n      const rawValue = cf.textValue ?? String(cf.booleanValue ?? cf.numberValue ?? '');\n      return {\n        type,\n        name: cf.definition.name,\n        value: type === 'text' ? sanitizeText(rawValue) : rawValue,\n      };\n    });\n  }\n\n  if (component.scorecardScores && component.scorecardScores.length > 0) {\n    config.scorecards = component.scorecardScores.map((sc) => ({\n      name: scorecardNames?.get(sc.scorecardId) ?? extractScorecardName(sc.scorecardId),\n      score: sc.totalScore,\n      maxScore: sc.maxTotalScore,\n    }));\n  }\n\n  return config;\n}\n\n// Enriched team data returned by fetchTeamById\nexport type TeamData = {\n  id: string;\n  displayName: string;\n  description?: string;\n  largeAvatarImageUrl?: string;\n  members?: Array<{ accountId: string; name: string; picture?: string }>;\n};\n\n// GraphQL query to fetch enriched team data — uses Teams v2 API\nconst GET_TEAM_QUERY = `\n  query getTeam($teamId: ID!, $siteId: String!) {\n    team {\n      teamV2(id: $teamId, siteId: $siteId) {\n        id\n        displayName\n        description\n        largeAvatarImageUrl\n        members(first: 50) {\n          nodes {\n            member {\n              accountId\n              name\n              picture\n            }\n          }\n        }\n      }\n    }\n  }\n`;\n\ntype GetTeamMember = {\n  accountId: string;\n  name: string;\n  picture?: string;\n};\n\ntype GetTeamResponse = {\n  data?: {\n    team: {\n      teamV2: {\n        id: string;\n        displayName: string;\n        description?: string;\n        largeAvatarImageUrl?: string;\n        members?: {\n          nodes?: Array<{ member: GetTeamMember }>;\n        };\n      } | null;\n    };\n  };\n  errors?: Array<{ message: string }>;\n};\n\nexport async function fetchTeamById(\n  config: Pick<ApiConfig, 'apiToken' | 'email' | 'baseUrl' | 'cloudId'>,\n  teamId: string\n): Promise<TeamData | null> {\n  const resolvedToken = resolveValue(config.apiToken);\n  const resolvedEmail = resolveValue(config.email);\n  const endpoint = `${config.baseUrl.replace(/\\/$/, '')}/gateway/api/graphql`;\n  const authHeader = buildAuthHeader(resolvedEmail, resolvedToken);\n\n  // The Teams v2 API expects the full ARI as ID — construct it if we only have a UUID\n  const teamAri = teamId.startsWith('ari:') ? teamId : `ari:cloud:identity::team/${teamId}`;\n\n  const response = await fetch(endpoint, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      Authorization: authHeader,\n      Accept: 'application/json',\n      'X-ExperimentalApi': 'teams-beta',\n    },\n    body: JSON.stringify({\n      query: GET_TEAM_QUERY,\n      variables: { teamId: teamAri, siteId: config.cloudId },\n    }),\n    signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n  });\n\n  if (!response.ok) {\n    console.warn(`Team API request failed for ${teamId} (HTTP ${response.status})`);\n    return null;\n  }\n\n  const result = (await response.json()) as GetTeamResponse;\n\n  if (result.errors) {\n    console.warn(`Team API GraphQL error for ${teamId}: ${result.errors[0]?.message}`);\n    return null;\n  }\n\n  if (!result.data) {\n    console.warn(`Team API returned no data for ${teamId}`);\n    return null;\n  }\n\n  const team = result.data.team?.teamV2;\n  if (!team) {\n    console.warn(`Team not found for ID ${teamId}`);\n    return null;\n  }\n\n  const members = team.members?.nodes?.length\n    ? team.members.nodes.map((n) => ({\n        accountId: n.member.accountId,\n        name: n.member.name,\n        picture: n.member.picture || undefined,\n      }))\n    : undefined;\n\n  return {\n    id: team.id,\n    displayName: team.displayName,\n    ...(team.description && { description: team.description }),\n    ...(team.largeAvatarImageUrl && { largeAvatarImageUrl: team.largeAvatarImageUrl }),\n    ...(members && { members }),\n  };\n}\n\n// GraphQL query to fetch all scorecards for the cloud instance\nconst GET_SCORECARDS_QUERY = `\n  query getScorecards($cloudId: ID!) {\n    compass {\n      scorecards(cloudId: $cloudId, query: { first: 100 }) {\n        __typename\n        ... on QueryError { message identifier }\n        ... on CompassScorecardConnection {\n          nodes {\n            id\n            name\n          }\n        }\n      }\n    }\n  }\n`;\n\ntype GetScorecardsResponse = {\n  data?: {\n    compass: {\n      scorecards: {\n        __typename: string;\n        nodes?: Array<{ id: string; name: string }>;\n        message?: string;\n      };\n    };\n  };\n  errors?: Array<{ message: string }>;\n};\n\nexport async function fetchScorecardNames(\n  config: Pick<ApiConfig, 'apiToken' | 'email' | 'baseUrl' | 'cloudId'>\n): Promise<Map<string, string>> {\n  const resolvedToken = resolveValue(config.apiToken);\n  const resolvedEmail = resolveValue(config.email);\n  const endpoint = `${config.baseUrl.replace(/\\/$/, '')}/gateway/api/graphql`;\n  const authHeader = buildAuthHeader(resolvedEmail, resolvedToken);\n\n  try {\n    const response = await fetch(endpoint, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Authorization: authHeader,\n        Accept: 'application/json',\n      },\n      body: JSON.stringify({\n        query: GET_SCORECARDS_QUERY,\n        variables: { cloudId: config.cloudId },\n      }),\n      signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n    });\n\n    if (!response.ok) {\n      console.warn(`Could not fetch scorecard names (HTTP ${response.status}), will use short IDs`);\n      return new Map();\n    }\n\n    const result = (await response.json()) as GetScorecardsResponse;\n    if (result.errors) {\n      console.warn(`Scorecard API GraphQL error: ${result.errors[0]?.message}, will use short IDs`);\n      return new Map();\n    }\n\n    const scorecards = result.data?.compass?.scorecards;\n    if (!scorecards?.nodes) {\n      const errorMsg = scorecards?.message || 'no data returned';\n      console.warn(`Could not fetch scorecard names (${errorMsg}), will use short IDs`);\n      return new Map();\n    }\n\n    const map = new Map<string, string>();\n    for (const sc of scorecards.nodes) {\n      map.set(sc.id, sc.name);\n    }\n    console.log(`Fetched ${map.size} scorecard name(s) from Compass API`);\n    return map;\n  } catch {\n    console.warn('Failed to fetch scorecard names, will use short IDs');\n    return new Map();\n  }\n}\n\nexport async function fetchComponents(config: ApiConfig, scorecardNames?: Map<string, string>): Promise<CompassConfig[]> {\n  const resolvedToken = resolveValue(config.apiToken);\n  const resolvedEmail = resolveValue(config.email);\n  const endpoint = `${config.baseUrl.replace(/\\/$/, '')}/gateway/api/graphql`;\n  const authHeader = buildAuthHeader(resolvedEmail, resolvedToken);\n\n  const components: CompassConfig[] = [];\n  let cursor: string | null = null;\n  let hasNextPage = true;\n\n  while (hasNextPage) {\n    const variables: Record<string, unknown> = {\n      cloudId: config.cloudId,\n      after: cursor,\n    };\n\n    const response = await fetch(endpoint, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        Authorization: authHeader,\n        Accept: 'application/json',\n      },\n      body: JSON.stringify({\n        query: SEARCH_COMPONENTS_QUERY,\n        variables,\n      }),\n      signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n    });\n\n    if (!response.ok) {\n      if (response.status === 401) {\n        throw new Error('Compass API authentication failed: invalid email or API token');\n      }\n      if (response.status === 403) {\n        throw new Error('Compass API authorization failed: insufficient permissions');\n      }\n      if (response.status === 429) {\n        throw new Error('Compass API rate limit exceeded: too many requests');\n      }\n      throw new Error(`Compass API request failed with status ${response.status}`);\n    }\n\n    const result = (await response.json()) as SearchComponentsResponse;\n\n    if (result.errors && result.errors.length > 0) {\n      throw new Error(`Compass GraphQL error: ${result.errors[0].message}`);\n    }\n\n    if (!result.data) {\n      throw new Error('Compass API returned no data');\n    }\n\n    const searchResult = result.data.compass.searchComponents;\n\n    if (searchResult.__typename === 'QueryError') {\n      throw new Error(`Compass API error: ${searchResult.message || 'Unknown error'}`);\n    }\n\n    if (!searchResult.nodes || !searchResult.pageInfo) {\n      throw new Error('Compass API returned unexpected response structure');\n    }\n\n    for (const node of searchResult.nodes) {\n      components.push(mapComponent(node.component, scorecardNames));\n    }\n\n    hasNextPage = searchResult.pageInfo.hasNextPage;\n    cursor = searchResult.pageInfo.endCursor;\n  }\n\n  return components;\n}\n\nconst UPDATE_COMPONENT_MUTATION = `\n  mutation updateComponent($id: ID!, $ownerId: ID!) {\n    compass {\n      updateComponent(input: { id: $id, ownerId: $ownerId }) {\n        success\n        errors { message }\n        componentDetails { id ownerId }\n      }\n    }\n  }\n`;\n\ntype UpdateComponentResponse = {\n  data?: {\n    compass: {\n      updateComponent: {\n        success: boolean;\n        errors: Array<{ message: string }> | null;\n        componentDetails?: { id: string; ownerId: string | null };\n      };\n    };\n  };\n  errors?: Array<{ message: string }>;\n};\n\nexport async function updateComponentOwner(\n  config: Pick<ApiConfig, 'apiToken' | 'email' | 'baseUrl'>,\n  componentId: string,\n  ownerAri: string\n): Promise<void> {\n  const resolvedToken = resolveValue(config.apiToken);\n  const resolvedEmail = resolveValue(config.email);\n  const endpoint = `${config.baseUrl.replace(/\\/$/, '')}/gateway/api/graphql`;\n  const authHeader = buildAuthHeader(resolvedEmail, resolvedToken);\n\n  const response = await fetch(endpoint, {\n    method: 'POST',\n    headers: {\n      'Content-Type': 'application/json',\n      Authorization: authHeader,\n      Accept: 'application/json',\n    },\n    body: JSON.stringify({\n      query: UPDATE_COMPONENT_MUTATION,\n      variables: { id: componentId, ownerId: ownerAri },\n    }),\n    signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Compass updateComponent request failed with status ${response.status}`);\n  }\n\n  const result = (await response.json()) as UpdateComponentResponse;\n\n  if (result.errors && result.errors.length > 0) {\n    throw new Error(result.errors[0].message);\n  }\n\n  const payload = result.data?.compass?.updateComponent;\n  if (payload?.errors && payload.errors.length > 0) {\n    throw new Error(`Compass update component error: ${payload.errors[0].message}`);\n  }\n}\n"],"mappings":"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","names":[]}