Skip to main content
Glama
attio-response.tsβ€’4.16 kB
/** * Utilities for handling Attio API responses * * Handles both Axios (res.data) and fetch/mock response formats */ /** * Interface for API response envelope */ interface ApiResponseEnvelope { data?: unknown; error?: unknown; } /** * Interface for raw note data from API */ interface RawNoteData { id?: | { note_id?: string; record_id?: string; workspace_id?: string; id?: string; } | string; note_id?: string; record_id?: string; workspace_id?: string; parent_object?: string; parent_record_id?: string; title?: string; content_markdown?: string; content_plaintext?: string; created_at?: string; updated_at?: string; tags?: unknown[]; meeting_id?: string; format?: string; } /** * Interface for normalized note structure */ export interface NormalizedNote extends Record<string, unknown> { id: { note_id: string | null; workspace_id: string | null; record_id: string | null; }; parent_object: string | null; parent_record_id: string | null; title: string | null; content_markdown: string | null; content_plaintext: string | null; content: string; created_at: string | null; updated_at: string | null; tags: unknown[]; meeting_id: string | null; format: string; } /** * Safely unwrap Attio API response envelope * Handles both Axios responses and direct API responses */ export function unwrapAttio<T>(res: unknown): T { const responseEnvelope = res as ApiResponseEnvelope; const envelope = responseEnvelope?.data ?? res; const envelopeObj = envelope as ApiResponseEnvelope; // If the envelope clearly looks like an error, just return it as-is and let the caller detect it if (envelopeObj?.error && !envelopeObj?.data) return envelope as T; return (envelopeObj?.data ?? envelope) as T; } /** * Normalize Attio note to consistent structure * Provides compatibility with record-style tests via record_id alias */ export function normalizeNote(note: RawNoteData): NormalizedNote { // Ensure we always have a base object to work with const source = note || {}; const idObj = source.id || {}; // Simplify ID extraction const rawId = source.note_id || source.record_id || (typeof idObj === 'object' && idObj !== null ? idObj.note_id : null) || (typeof idObj === 'object' && idObj !== null ? idObj.record_id : null) || (typeof idObj === 'object' && idObj !== null ? idObj.id : null) || (typeof source.id === 'string' ? source.id : null); const normalized = { id: { note_id: rawId, workspace_id: source.workspace_id || (typeof idObj === 'object' && idObj !== null ? idObj.workspace_id : null) || null, record_id: rawId, // alias for tests }, parent_object: source.parent_object || null, parent_record_id: source.parent_record_id || null, title: source.title || null, content_markdown: source.content_markdown || null, content_plaintext: source.content_plaintext || null, content: source.content_markdown || source.content_plaintext || '', created_at: source.created_at || null, updated_at: source.updated_at || null, tags: Array.isArray(source.tags) ? source.tags : [], meeting_id: source.meeting_id || null, format: source.format || 'markdown', }; return normalized; } /** * Normalize array of notes */ export function normalizeNotes(notes: RawNoteData[]): NormalizedNote[] { if (!Array.isArray(notes)) return []; return notes.map(normalizeNote).filter(Boolean); } /** * Coerce format to Attio-accepted values and preserve content */ export function coerceNoteFormat( format?: string, content?: string ): { format: 'markdown' | 'plaintext'; content: string } { // Convert html to markdown to preserve HTML tags, otherwise default to markdown or plaintext const attioFormat = format === 'html' || format === 'markdown' ? 'markdown' : 'plaintext'; // Preserve content as-is - tests expect HTML content to be unchanged const processedContent = content || ''; return { format: attioFormat, content: processedContent, }; }

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/kesslerio/attio-mcp-server'

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