npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@lantern-ai/hubspot-core-utility

v1.1.6

Published

Shared HubSpot helpers for React and Node usage

Readme

@lantern/hubspot-core-utility

A comprehensive utility package for integrating HubSpot services into both client-side (React) and server-side (Node.js) applications.

Features and Functionalities

This utility provides a robust set of tools to interact with the HubSpot API, covering everything from configuration and client management to specific CRM operations.

Core Concepts

The package is designed with flexibility in mind, offering two primary ways to interact with HubSpot:

  1. Modern Client (createHubspotClient): A factory function that returns a fully typed HubSpot API client. This is the recommended approach for new integrations.
  2. Legacy Helper Functions: A suite of standalone, exported functions for common operations (e.g., getHubSpotContact, createHubSpotDeal). These are great for quick, one-off tasks or for maintaining existing codebases.

Configuration Management

Secure and straightforward configuration is handled via a set of in-memory helpers, ensuring your API keys are managed safely on the server.

  • initializeHubspotFromKey(key): The primary method to set up the utility with your HubSpot API key.
  • setHubspotConfig(config), getHubspotConfig(), clearHubspotConfig(): Granular functions to manage the HubSpot configuration object manually.

React Hook

For client-side applications, the package provides a custom hook to interact with HubSpot data.

  • useHubspotContacts(): A React hook that simplifies fetching and managing HubSpot contacts within your components.

Server-Side API Functions

A rich set of functions to manage various HubSpot objects directly from your backend.

Contact Management

  • getHubSpotContact(id)
  • createHubSpotContact(properties)
  • updateHubSpotContact(id, properties)
  • searchContactsByEmail(email)

Deal Management

  • getHubSpotDeal(id)
  • createHubSpotDeal(properties)
  • updateHubSpotDeal(id, properties)
  • getAllHubSpotDeals()
  • searchHubSpotDeals(query)
  • getHubSpotDealDetails(id)

Product Management

  • getHubSpotProduct(id)
  • getHubSpotProducts()
  • getHubSpotProductBySku(sku)

Other Utilities

  • Associations: createHubSpotAssociation(...) to link different CRM objects.
  • Timeline Events: createTimelineEvent(...) to add custom events to an object's timeline.
  • Conversion Tracking: trackHubSpotConversion(...) for marketing analytics.
  • Low-Level Access: hubspotAxios is exported, giving you direct access to the pre-configured Axios instance for custom or unsupported API calls.

Quick start

Install (from monorepo use local build / link; when published use npm/yarn):

# from package folder
npm install
npm run build
# in consumer project (example local link)
npm link @lantern/hubspot-core-utility

Initialize once on server startup:

// server/index.ts (or next.js getServerSideProps / server bootstrap)
import { initializeHubspotFromKey } from '@lantern/hubspot-core-utility';

initializeHubspotFromKey(process.env.HUBSPOT_API_KEY);

If your package does not export initializeHubspotFromKey, use:

import { setHubspotConfig } from '@lantern/hubspot-core-utility';
setHubspotConfig({ apiKey: process.env.HUBSPOT_API_KEY });

After initialization, anywhere in server or client code (hook will prefer stored config / env fallback):

import { createHubspotClient } from '@lantern/hubspot-core-utility';

const client = createHubspotClient(); // uses stored config or process.env.HUBSPOT_API_KEY
await client.upsertContactByEmail({ email: '[email protected]', firstname: 'A' });

API

  • initializeHubspotFromKey(hapikey?: string) — convenience initializer that calls setHubspotConfig under the hood.
  • setHubspotConfig(cfg: Partial) — set in-memory config (server startup).
  • getHubspotConfig() — read in-memory config.
  • createHubspotClient(config?: HubspotConfig) — returns a client with methods:
    • getContactByEmail(email)
    • createContact(contact)
    • upsertContactByEmail(contact)
    • axiosInstance (raw axios)
  • useHubspotContacts(config?: HubspotConfig) — React hook returning:
    • loading, contacts, error, client, fetchByEmail(email), upsertContact(contact)

Example: Server initialization (recommended)

// server/bootstrap.ts
import { initializeHubspotFromKey } from '@lantern/hubspot-core-utility';

export function bootstrap() {
  // Only run on server
  if (typeof window === 'undefined') {
    initializeHubspotFromKey(process.env.HUBSPOT_API_KEY);
  }
}

Example: React component using the hook

// filepath: examples/components/ContactManager.tsx
import React, { useEffect } from 'react';
import { useHubspotContacts } from '@lantern/hubspot-core-utility';

export function ContactManager({ email }: { email?: string }) {
  const { loading, contacts, fetchByEmail, upsertContact } = useHubspotContacts();

  useEffect(() => {
    if (email) {
      fetchByEmail(email).catch(console.error);
    }
  }, [email, fetchByEmail]);

  async function handleUpsert() {
    try {
      await upsertContact({ email: '[email protected]', firstname: 'New', lastname: 'Cust' });
      // maybe re-fetch or show success
    } catch (e) {
      console.error(e);
    }
  }

  return (
    <div>
      <button onClick={handleUpsert} disabled={loading}>
        Upsert demo contact
      </button>
      {loading && <div>Loading…</div>}
      {contacts?.length ? (
        <div>
          <h4>Contact</h4>
          <pre>{JSON.stringify(contacts[0], null, 2)}</pre>
        </div>
      ) : null}
    </div>
  );
}

Notes:

  • The hook does NOT auto-fetch on mount (call fetchByEmail explicitly). This keeps behavior predictable and testable.
  • The hook uses the in-memory config (set via initializeHubspotFromKey / setHubspotConfig) or falls back to process.env.HUBSPOT_API_KEY.

Example: Server endpoint (Express)

// server/routes/hubspot.ts
import express from 'express';
import { createHubspotClient } from '@lantern/hubspot-core-utility';
const router = express.Router();

router.post('/contacts/upsert', async (req, res) => {
  try {
    const client = createHubspotClient();
    const contact = await client.upsertContactByEmail(req.body);
    res.json(contact);
  } catch (err: any) {
    res.status(err?.status || 500).json({ message: err?.message || 'error' });
  }
});

export default router;

Examples: Using the full public API

The package entrypoint exports the primary helpers and the convenience (legacy) wrappers so you can import everything from the package root.

  • Recommended: initialize the in-memory config on server startup (hapikey). For tests or browser-like environments use setHubspotConfig instead.
import {
  // core helpers
  createHubspotClient,
  useHubspotContacts,
  // config helpers
  initializeHubspotFromKey,
  setHubspotConfig,
  getHubspotConfig,
  clearHubspotConfig,
  // legacy convenience wrappers
  getHubSpotContact,
  createHubSpotContact,
  updateHubSpotContact,
  getHubSpotProduct,
  getHubSpotProducts,
  getHubSpotProductBySku,
  createHubSpotDeal,
  updateHubSpotDeal,
  getHubSpotDeal,
  getHubSpotDealDetails,
  getHubSpotDealRawProperties,
  getAllHubSpotDeals,
  searchHubSpotDeals,
  searchContactsByEmail,
  createHubSpotAssociation,
  createTimelineEvent,
  trackHubSpotConversion,
  hubspotAxios,
} from '@lantern/hubspot-core-utility';

Server initialization (recommended):

// server/bootstrap.ts
import { initializeHubspotFromKey } from '@lantern/hubspot-core-utility';

if (typeof window === 'undefined') {
  initializeHubspotFromKey(process.env.HUBSPOT_API_KEY);
}

Using the client directly:

const client = createHubspotClient();
await client.upsertContactByEmail({ email: '[email protected]', firstname: 'A' });

Using the legacy convenience wrappers (examples):

// read a contact
const contact = await getHubSpotContact('contact-id');

// create / update contact
const created = await createHubSpotContact({ email: '[email protected]', firstname: 'New' });
await updateHubSpotContact(created.id, { lastname: 'Customer' });

// products
const products = await getHubSpotProducts();
const bySku = await getHubSpotProductBySku('sku-123');

// deals
const deal = await createHubSpotDeal({ dealname: 'Purchase', amount: 100 });
await updateHubSpotDeal(deal.id, { amount: 120 });
const dealDetails = await getHubSpotDealDetails(deal.id);

// raw properties & associations
const raw = await getHubSpotDealRawProperties(deal.id);

// search
const foundContacts = await searchContactsByEmail('[email protected]');
const searchDeals = await searchHubSpotDeals([], ['dealname'], 50);

// create association
await createHubSpotAssociation('deals', deal.id, 'contacts', contact?.id || '');

// optional timeline event (non-fatal)
await createTimelineEvent(contact?.id || '', { templateId: 'template-1', properties: { note: 'Test event' } });

// track conversion (creates deal, optionally updates contact/associations)
await trackHubSpotConversion({ contactId: contact?.id, amount: 200, productId: 123 });

// if you need raw axios instance
hubspotAxios.request({ method: 'get', url: '/crm/v3/objects/contacts' });

Notes

  • Most helpers are server-oriented and assume the hapikey or access token is only available server-side. Do not call initializeHubspotFromKey from client bundles — it includes a runtime guard and will throw if executed where window is defined. Use setHubspotConfig in tests or browser-like environments.

Local demo setup (examples/demo + examples/react)

This repository includes a small Express demo server (examples/demo) and a Vite + React demo app (examples/react). The React app calls the demo server, so your HubSpot credentials remain server-side.

Follow these steps to run both locally:

  1. Prepare and start the demo server
# Install server deps
cd examples/demo
npm install

# Add your HubSpot credential to a local .env file (Private App token is recommended).
# Replace the value below with your own token (starts with "pat-")
# Do NOT commit this file or share the token publicly.
echo "HUBSPOT_ACCESS_TOKEN=pat-YOUR_PRIVATE_APP_TOKEN" > .env

# Start the server (reads .env when started). You can also pass the token inline:
# HUBSPOT_ACCESS_TOKEN=pat-YOUR_PRIVATE_APP_TOKEN npm run dev

# Start in the current shell (so you can see logs):
export $(grep -v '^#' .env | xargs)
npm run dev

Server endpoints (default PORT 3001):

  • GET /health
  • GET /[email protected]
  • POST /contacts/upsert (JSON body { email, firstname, lastname })
  1. Prepare and start the React demo app
# In a separate terminal
cd examples/react
npm install

# Optional: tell the Vite dev server where the demo server is running.
# By default the client uses http://localhost:3001. To override, create a Vite env file:
echo "VITE_DEMO_SERVER=http://localhost:3001" > .env

# Start the React dev server
npm run dev

Open the React app at: http://localhost:5173/ The app will call the demo server (http://localhost:3001) which performs HubSpot API requests server-side.

Security notes

  • Always keep HubSpot credentials server-side. Use a Private App token (pat-...) when interacting with CRM v3 endpoints. Developer API keys / hapikeys (na2-...) are legacy and often rejected by CRM v3 endpoints.
  • Never commit .env or secrets into git. Add examples/demo/.env and examples/react/.env to your global .gitignore or local ignore rules.
  • If an access token is accidentally exposed, rotate/revoke it in HubSpot immediately.

Troubleshooting

  • CORS errors in the browser (preflight) usually mean the client tried to call api.hubapi.com directly. Make sure the React app is calling the demo server endpoints (GET /contact, POST /contacts/upsert) and not HubSpot's API URLs.

  • If the demo server returns 401 Unauthorized:

    • Confirm HUBSPOT_ACCESS_TOKEN is present in examples/demo/.env and the server was restarted after adding it.
    • Verify the token works directly against HubSpot:
# Replace TOKEN and an email to test
curl -s -X POST 'https://api.hubapi.com/crm/v3/objects/contacts/search' \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer TOKEN" \
  -d '{"filterGroups":[{"filters":[{"propertyName":"email","operator":"EQ","value":"[email protected]"}]}],"properties":["email","firstname","lastname"]}' | jq .
  • To see detailed server errors, run the demo server in the foreground (do not run it as a background job) and inspect the console logs while issuing requests.

Convenience (optional)

  • If you'd like to start both servers with one command you can use concurrently or npm-run-all. Example (add to repo-level scripts):
"scripts": {
  "examples:demo:start": "cd examples/demo && export $(grep -v '^#' .env | xargs) && npm run dev",
  "examples:react:start": "cd examples/react && npm run dev",
  "examples:start": "concurrently \"npm run examples:demo:start\" \"npm run examples:react:start\""
}

(Install concurrently as a dev dependency if you use the above.)


Build & test

From package root:

npm install
npm run build
npm test

Security notes

  • Do NOT call initializeHubspotFromKey / setHubspotConfig from client-side code. Only initialize on server. Exposing hapikey in browser will compromise your HubSpot account.
  • Prefer server-side usage (API routes, server-rendered pages). For client needs, provide a server proxy endpoint that uses this utility internally.

Note: initializeHubspotFromKey includes a runtime guard and will throw if invoked in a browser-like environment (for example when window is defined or in jsdom). This helps prevent accidental client-side initialization and leaking of the hapikey. For tests or any environment where window exists, call setHubspotConfig({ apiKey: '...' }) instead.