UNPKG

@spotable/attio-sdk

Version:
135 lines (116 loc) 3.67 kB
import fetch, { Response } from "node-fetch"; import ora from "ora"; import logger from "./logger"; export interface AttioObject { id: { workspace_id: string; object_id: string; }; api_slug: string; singular_noun: string; plural_noun: string; created_at: string; updated_at?: string; } export interface AttioAttribute { id: { workspace_id: string; object_id: string; attribute_id: string; }; title: string; description: string | null; api_slug: string; type: string; is_system_attribute: boolean; is_writable: boolean; is_required: boolean; is_unique: boolean; is_multiselect: boolean; is_default_value_enabled: boolean; is_archived: boolean; default_value: any; relationship: any; config: Record<string, any>; created_at: string; } class HTTPResponseError extends Error { constructor(public response: Response) { super(`HTTP Error Response: ${response.status} ${response.statusText}`); this.response = response; } } async function logError(error: unknown): Promise<void> { if (error instanceof HTTPResponseError) { const body = await error.response.json(); logger.error(`API error (${error.response.status}): ${JSON.stringify(body)}`); } else { logger.error(`Error fetching schema`, { error }); } } async function checkStatus<R>(response: Response): Promise<R> { if (response.ok) { return response.json() as R; } throw new HTTPResponseError(response); } async function fetchAttioObjects(apiKey: string): Promise<AttioObject[]> { const fetchLoader = ora("Fetching Attio objects").start(); try { const response = await fetch("https://api.attio.com/v2/objects", { method: "GET", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, }); const body = await checkStatus<{ data: AttioObject[] }>(response); if (!response.ok) { logger.error(`Failed to fetch objects: ${response.statusText}`, { response: body, }); throw new Error(`Failed to fetch objects: ${response.statusText}`); } const objects = body.data; fetchLoader.succeed(`Found ${objects.length} objects`); return objects; } catch (error) { fetchLoader.fail("Failed to fetch Attio objects"); await logError(error); throw error; } } async function fetchAttioAttributes(apiKey: string, object: AttioObject): Promise<AttioAttribute[]> { const fetchLoader = ora(`Fetching attributes for ${object.singular_noun}`).start(); try { const response = await fetch(`https://api.attio.com/v2/objects/${object.api_slug}/attributes`, { method: "GET", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, }); const body = await checkStatus<{ data: AttioAttribute[] }>(response); const attributes = body.data; fetchLoader.succeed(`Found ${attributes.length} attributes for ${object.singular_noun}`); return attributes; } catch (error) { fetchLoader.fail(`Failed to fetch attributes for ${object.singular_noun}`); await logError(error); throw error; } } export async function fetchAttioSchema(apiKey: string) { const fetchLoader = ora("Fetching Attio schema").start(); const objects = await fetchAttioObjects(apiKey); const attributes: Record<string, AttioAttribute[]> = {}; for (const object of objects) { const objectAttributes = await fetchAttioAttributes(apiKey, object); attributes[object.api_slug] = objectAttributes; } fetchLoader.succeed("Attio schema fetched successfully"); return { objects, attributes, }; }