Skip to main content
Glama
personal-name-parser.tsβ€’3.52 kB
/** * Utility for parsing and handling personal-name fields * Addresses issue #409 - Personal name field type requires special handling */ /** * Parse a personal name value into Attio's expected format * Supports both string format ("John Doe") and structured format * * @param value - The raw name value (string or object) * - String: Will be parsed into first_name, last_name, and full_name * - Object: Expected to contain first_name, last_name, middle_name, title fields * - null/undefined: Returns null * * @returns Structured name object with the following fields, or null: * - first_name: The person's first name * - last_name: The person's last name (optional) * - middle_name: The person's middle name (optional, preserved from object input) * - title: Professional title (optional, preserved from object input) * - full_name: Complete name string (auto-generated if not provided) * * @example * // String input * parsePersonalName('John Doe') * // Returns: { first_name: 'John', last_name: 'Doe', full_name: 'John Doe' } * * @example * // Object input * parsePersonalName({ first_name: 'Jane', last_name: 'Smith', title: 'Dr.' }) * // Returns: { first_name: 'Jane', last_name: 'Smith', title: 'Dr.', full_name: 'Dr. Jane Smith' } * * @example * // Single name * parsePersonalName('Madonna') * // Returns: { first_name: 'Madonna', full_name: 'Madonna' } */ export function parsePersonalName( value: unknown ): Record<string, unknown> | null { if (value === null || value === undefined) { return null; } if (typeof value === 'string') { // Parse string name into first/last name structure const trimmed = value.trim(); if (!trimmed) { return null; } const parts = trimmed.split(/\s+/); if (parts.length === 1) { // Only one name part - treat as first name return { first_name: parts[0], full_name: parts[0], }; } else if (parts.length === 2) { // Standard first last format return { first_name: parts[0], last_name: parts[1], full_name: trimmed, }; } else { // Multiple parts - first, middle(s), last const firstName = parts[0]; const lastName = parts[parts.length - 1]; return { first_name: firstName, last_name: lastName, full_name: trimmed, }; } } else if (typeof value === 'object' && value !== null) { // Already structured - ensure it has required fields const structured = value as Record<string, unknown>; const result: Record<string, unknown> = {}; // Copy over known fields if (structured.first_name) result.first_name = structured.first_name; if (structured.last_name) result.last_name = structured.last_name; if (structured.middle_name) result.middle_name = structured.middle_name; if (structured.title) result.title = structured.title; // Generate full_name if not provided if (!structured.full_name) { const nameParts = []; if (structured.title) nameParts.push(String(structured.title)); if (structured.first_name) nameParts.push(String(structured.first_name)); if (structured.middle_name) nameParts.push(String(structured.middle_name)); if (structured.last_name) nameParts.push(String(structured.last_name)); result.full_name = nameParts.filter(Boolean).join(' '); } else { result.full_name = structured.full_name; } return result; } return null; }

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