UNPKG

@hoover-institution/hubspot-lib

Version:

A toolkit for deep integration with HubSpot's Marketing Events API with a plugin-based architecture.

141 lines (128 loc) 4.49 kB
/** * IN DEVELOPMENT * * Manages HubSpot contact operations using the HubSpot CRM API. * Requires the HUBSPOT_KEY environment variable for authentication. * * @class ContactManager * @private */ import axios from "axios"; export class ContactManager { #client; constructor() { this.#client = axios.create({ baseURL: "https://api.hubapi.com/crm/v3/", headers: { Authorization: `Bearer ${process.env.HUBSPOT_KEY}`, "Content-Type": "application/json", }, timeout: 5000, }); } /** * @typedef {Object} HubSpotContact * @property {string} id * @property {Object} properties * @property {string} properties.createdate * @property {string} properties.email * @property {string} properties.firstname * @property {string} properties.hs_object_id * @property {string} properties.lastmodifieddate * @property {string} properties.lastname * @property {string} createdAt * @property {string} updatedAt * @property {boolean} archived */ /** * Retrieves a contact by their email address, or creates one if not found. * * @async * @param {string} email - The email address of the contact to search for. * @param {string} [fullName=""] - The full name to use if creating a new contact. * @returns {Promise<HubSpotContact>} The contact object, newly created or found. * @throws {Error} If the request fails for reasons other than not found. */ async getContactByEmail(email, fullName = "") { try { const response = await this.#client.post("/objects/contacts/search", { filterGroups: [ { filters: [{ propertyName: "email", operator: "EQ", value: email }], }, ], properties: ["email", "firstname", "lastname"], }); if (!response.data.results[0]) { const [firstName, ...lastNameParts] = fullName.trim().split(" "); const lastName = lastNameParts.join(" "); const createResponse = await this.#client.post("/objects/contacts", { properties: { email, firstname: firstName || "", lastname: lastName || "", }, }); return createResponse.data; } return response.data.results[0] || null; } catch (error) { console.error("[ContactManager] Error in getContactByEmail:", error); if (error.response?.status === 404) return null; throw error; } } // getContactById /** * Retrieves a contact by their unique HubSpot ID. * * @async * @param {string} contactId - The unique HubSpot ID of the contact. * @returns {Promise<HubSpotContact|null>} The contact object if found, otherwise null. * @throws {Error} If the request fails for reasons other than not found. */ async getContactById(contactId) { try { const response = await this.#client.get( `/objects/contacts/${contactId}`, { params: { properties: ["email", "firstname", "lastname"].join(",") }, } ); return response.data || null; } catch (error) { if (error.response?.status === 404) return null; throw error; } } /** * @typedef {Object} ContactListMembership * @property {string} listId - The unique identifier of the list. * @property {number} listVersion - The version number of the list. * @property {boolean} isPublicList - Whether the list is public. * @property {string} firstAddedTimestamp - The ISO timestamp when the contact was first added to the list. * @property {string} lastAddedTimestamp - The ISO timestamp when the contact was last added to the list. */ /** * Retrieves the contact lists that a contact with the specified email belongs to. * * @async * @param {string} email - The email address of the contact to look up. * @returns {Promise<ContactListMembership[]|null>} A promise that resolves to an array of contact list memberships, * or null if the contact does not exist. * @throws {Error} Throws an error if the API request fails. */ async getContactLists(email) { const contact = await this.getContactByEmail(email); if (!contact) return null; const recordId = contact.id; try { const response = await this.#client.get( `https://api.hubapi.com/crm/v3/lists/records/0-1/${recordId}/memberships` ); return response.data.results || []; } catch (error) { throw error; } } }