Skip to main content
Glama
fields.ts4.85 kB
/** * Jira Fields API endpoints. * @module jira/endpoints/fields */ import { getClient } from '../client.js'; import { createLogger } from '../../utils/logger.js'; const logger = createLogger('jira-fields'); /** * Field representation. */ export interface JiraField { id: string; key?: string; name: string; custom: boolean; orderable: boolean; navigable: boolean; searchable: boolean; clauseNames: string[]; schema?: { type: string; items?: string; system?: string; custom?: string; customId?: number; }; untranslatedName?: string; } /** * Common custom field names that are frequently used. */ export const COMMON_CUSTOM_FIELDS = [ 'Story Points', 'Sprint', 'Team', 'Epic Name', 'Start date', 'Due date', 'Story point estimate', 'Flagged', ]; // Cache for discovered fields let fieldsCache: JiraField[] | null = null; let customFieldsMap: Map<string, string> | null = null; /** * Gets all fields available in Jira. * * @param useCache - Whether to use cached results (default: true) * @returns List of all fields * * @example * const fields = await getAllFields(); */ export async function getAllFields( useCache: boolean = true ): Promise<JiraField[]> { if (useCache && fieldsCache) { return fieldsCache; } logger.debug('Getting all fields'); const fields = await getClient().get<JiraField[]>('/rest/api/3/field'); fieldsCache = fields; // Build custom fields map customFieldsMap = new Map(); for (const field of fields) { if (field.custom) { customFieldsMap.set(field.name.toLowerCase(), field.id); } } return fields; } /** * Gets only custom fields. * * @returns List of custom fields */ export async function getCustomFields(): Promise<JiraField[]> { const fields = await getAllFields(); return fields.filter((f) => f.custom); } /** * Searches for fields by name (fuzzy match). * * @param query - Search query * @returns Matching fields * * @example * const fields = await searchFields('story'); * // Returns fields like 'Story Points', 'Story point estimate', etc. */ export async function searchFields(query: string): Promise<JiraField[]> { const fields = await getAllFields(); const lowerQuery = query.toLowerCase(); return fields.filter( (f) => f.name.toLowerCase().includes(lowerQuery) || f.id.toLowerCase().includes(lowerQuery) || f.clauseNames.some((c) => c.toLowerCase().includes(lowerQuery)) ); } /** * Gets the field ID for a field name. * Useful for custom fields where you know the name but need the ID. * * @param fieldName - The field name to look up * @returns The field ID or null if not found * * @example * const storyPointsId = await getFieldId('Story Points'); * // Returns something like 'customfield_10016' */ export async function getFieldId(fieldName: string): Promise<string | null> { const fields = await getAllFields(); const field = fields.find( (f) => f.name.toLowerCase() === fieldName.toLowerCase() ); return field?.id ?? null; } /** * Gets commonly used custom field IDs. * Auto-discovers Story Points, Sprint, Team, etc. * * @returns Map of field names to their IDs */ export async function getCommonCustomFieldIds(): Promise< Record<string, string> > { const fields = await getAllFields(); const result: Record<string, string> = {}; for (const fieldName of COMMON_CUSTOM_FIELDS) { const field = fields.find( (f) => f.name.toLowerCase() === fieldName.toLowerCase() ); if (field) { result[fieldName] = field.id; } } return result; } /** * Builds a minimal fields list including common custom fields. * Used for data minimization strategy. * * @param baseFields - Base fields to include * @returns Fields array with custom field IDs */ export async function buildMinimalFieldsList( baseFields: string[] = [ 'summary', 'status', 'assignee', 'priority', 'issuetype', 'updated', 'parent', ] ): Promise<string[]> { const customFields = await getCommonCustomFieldIds(); const customFieldIds = Object.values(customFields); return [...baseFields, ...customFieldIds]; } /** * Clears the fields cache. * Call this if fields have been added/removed. */ export function clearFieldsCache(): void { fieldsCache = null; customFieldsMap = null; } /** * Gets field suggestions for autocomplete. * * @param prefix - Prefix to match * @param limit - Maximum results (default: 10) * @returns Matching field names and IDs */ export async function getFieldSuggestions( prefix: string, limit: number = 10 ): Promise<Array<{ name: string; id: string; custom: boolean }>> { const fields = await searchFields(prefix); return fields.slice(0, limit).map((f) => ({ name: f.name, id: f.id, custom: f.custom, })); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/icy-r/jira-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server