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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/api-esign-hellosign

v1.0.1

Published

HelloSign (Dropbox Sign) e-signature provider for molecule.dev.

Readme

@molecule/api-esign-hellosign

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

HelloSign (Dropbox Sign) e-signature provider for molecule.dev.

Implements the @molecule/api-esign EsignProvider contract against the HelloSign v3 REST API: create signature requests (raw Buffer upload, hosted { url }, or { templateId, prefill } template), poll status, cancel, download the signed PDF, and verify + normalize webhook events (HMAC-SHA256, keyed by the API key).

Quick Start

import { setProvider } from '@molecule/api-esign'
import { provider } from '@molecule/api-esign-hellosign'

setProvider(provider)

Type

provider

Installation

npm install @molecule/api-esign-hellosign @molecule/api-bond @molecule/api-esign @molecule/api-secrets

API

Interfaces

CreateSignatureRequestInput

Input to {@link EsignProvider.createSignatureRequest}.

interface CreateSignatureRequestInput {
  /** Human-readable title for the request, shown to signers. */
  title: string
  /** Ordered list of signers. */
  signers: Signer[]
  /** The document to be signed. */
  document: EsignDocument
  /** Optional list of CC email addresses that receive a copy on completion. */
  ccs?: string[]
  /** Optional message included in the signing invitation. */
  message?: string
}

EsignProvider

Abstract e-signature provider interface. All vendor bonds (HelloSign / Dropbox Sign, DocuSign, OpenSign, Adobe Sign, etc.) must implement this interface so application code stays vendor-agnostic.

interface EsignProvider {
  /**
   * Creates a new signature request. The document may be supplied as a raw
   * Buffer, a hosted URL, or a vendor template reference with prefill.
   *
   * @param input - Title, signers, document, and optional CC/message fields.
   * @returns The newly-created signature request, normalized.
   */
  createSignatureRequest(input: CreateSignatureRequestInput): Promise<SignatureRequest>
  /**
   * Retrieves the current status of an existing signature request.
   *
   * @param id - Provider-issued signature request id.
   * @returns The current state of the signature request, normalized.
   */
  getSignatureRequest(id: string): Promise<SignatureRequest>
  /**
   * Cancels a pending signature request. No-op for already-completed requests
   * (providers either return success or 4xx; this method normalizes to void).
   *
   * @param id - Provider-issued signature request id.
   */
  cancelSignatureRequest(id: string): Promise<void>
  /**
   * Downloads the signed document (typically PDF) as a Buffer. Available
   * once the request status is `signed`.
   *
   * @param id - Provider-issued signature request id.
   * @returns The signed document bytes.
   */
  getSignedDocument(id: string): Promise<Buffer>
  /**
   * Verifies and parses an inbound webhook callback from the provider.
   * Implementations MUST verify the request authenticity (e.g. via HMAC)
   * and throw on signature mismatch.
   *
   * @param headers - The HTTP request headers as a plain object.
   * @param body - The parsed JSON body of the webhook request.
   * @returns A normalized event describing what happened.
   */
  processWebhook(
    headers: Record<string, string | string[] | undefined>,
    body: unknown,
  ): Promise<EsignWebhookEvent>
}

EsignWebhookEvent

Normalized webhook event produced by {@link EsignProvider.processWebhook}.

interface EsignWebhookEvent {
  /** Type of the underlying event. */
  type: EsignWebhookEventType
  /** Signature request id this event refers to. */
  signatureRequestId: string
  /** Email of the signer involved, when applicable (e.g. signed / declined). */
  signerEmail?: string
  /** The original provider payload, for diagnostic / audit purposes. */
  raw: unknown
}

SignatureRequest

Normalized signature request returned by all EsignProvider methods.

interface SignatureRequest {
  /** Provider-issued signature request id. */
  id: string
  /** Aggregate status for the whole request. */
  status: SignatureRequestStatus
  /** Per-signer breakdown including individual status and timestamp. */
  signers: SignerWithStatus[]
  /** ISO-8601 timestamp at which the request reached `signed` status. */
  signedAt?: string
}

Signer

A signer participating in a signature request.

interface Signer {
  /** Display name shown to the signer in invitations. */
  name: string
  /** Email address used to deliver the signing invitation. */
  email: string
  /** Optional role label (e.g. `'Tenant'`, `'Landlord'`). Some providers use this for template binding. */
  role?: string
}

SignerWithStatus

A signer plus their current status within a signature request.

interface SignerWithStatus extends Signer {
  /** Current status for this signer. */
  status: SignerStatus
  /** ISO-8601 timestamp at which the signer signed, when applicable. */
  signedAt?: string
}

Types

EsignDocument

The document body for a new signature request. Three forms are supported:

  1. A raw Buffer (uploaded via multipart upload by the provider).
  2. A reference to an externally-hosted document via { url, filename? }.
  3. A reference to a vendor-side template via { templateId, prefill? }, where prefill populates merge fields defined on the template.
type EsignDocument =
  | Buffer
  | {
      url: string
      filename?: string
    }
  | {
      templateId: string
      prefill?: Record<string, string | number | boolean>
    }

EsignWebhookEventType

Webhook event types normalized across providers.

type EsignWebhookEventType =
  | 'signature_request_signed'
  | 'signature_request_all_signed'
  | 'signature_request_declined'
  | 'signature_request_cancelled'
  | 'signature_request_expired'
  | 'unknown'

SignatureRequestStatus

Aggregate status for a signature request as a whole.

  • awaiting_signatures — at least one signer has not yet signed
  • signed — every signer has signed
  • declined — at least one signer declined
  • cancelled — request was cancelled by the requester
  • expired — request window elapsed before completion
type SignatureRequestStatus =
  'awaiting_signatures' | 'signed' | 'declined' | 'cancelled' | 'expired'

SignerStatus

Per-signer status within a signature request.

  • pending — invitation sent, awaiting action
  • signed — signer has completed and signed
  • declined — signer explicitly declined
  • expired — signature window elapsed before action
type SignerStatus = 'pending' | 'signed' | 'declined' | 'expired'

Functions

cancelSignatureRequest(id)

Cancels a pending HelloSign signature request.

function cancelSignatureRequest(id: string): Promise<void>
  • id — HelloSign signature_request_id.

createSignatureRequest(input)

Creates a new signature request via HelloSign. Routes between three endpoints depending on the document form:

  • Buffer → signature_request/send (multipart)
  • URL → signature_request/send (JSON file_url)
  • Template → signature_request/send_with_template
function createSignatureRequest(input: CreateSignatureRequestInput): Promise<SignatureRequest>
  • input — The signature request input.

Returns: The newly-created normalized signature request.

getSignatureRequest(id)

Retrieves the current state of a HelloSign signature request.

function getSignatureRequest(id: string): Promise<SignatureRequest>
  • id — HelloSign signature_request_id.

Returns: The normalized signature request.

getSignedDocument(id)

Downloads the signed PDF for a HelloSign signature request.

function getSignedDocument(id: string): Promise<Buffer<ArrayBufferLike>>
  • id — HelloSign signature_request_id.

Returns: The signed document bytes.

processWebhook(_headers, body)

Verifies and parses an inbound HelloSign webhook callback. The HelloSign webhook payload arrives form-encoded with a single json field whose value is the JSON body. The body contains event.event_hash, computed as hmac_sha256(api_key, event_time + event_type).

Implementations that pre-parse the form into { json: '...' } should pass the resulting object directly. The provider also tolerates a body already shaped like the inner event payload.

function processWebhook(
  _headers: Record<string, string | string[] | undefined>,
  body: unknown,
): Promise<EsignWebhookEvent>
  • _headers — The HTTP request headers (unused; HelloSign places the hash inside the body).
  • body — The parsed request body.

Returns: The normalized webhook event.

Constants

esignHellosignSecretDefinitions

Secret definitions required by the Dropbox Sign (HelloSign) e-signature bond.

const esignHellosignSecretDefinitions: SecretDefinition[]

provider

The HelloSign provider implementing the EsignProvider interface.

const provider: EsignProvider

Core Interface

Implements @molecule/api-esign interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setProvider } from '@molecule/api-esign'
import { provider } from '@molecule/api-esign-hellosign'

export function setupEsignHellosign(): void {
  setProvider(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-bond ^1.0.1
  • @molecule/api-esign ^1.0.1
  • @molecule/api-secrets ^1.0.1

Environment Variables

Runtime Dependencies

  • @molecule/api-bond

  • @molecule/api-esign

  • @molecule/api-secrets

  • Webhook provisioning is manual. Configure the callback URL in the Dropbox Sign dashboard (Settings → API → Account callback) — this bond does not register it. Events arrive application/x-www-form-urlencoded with a single json field: mount the route with a urlencoded (or multipart) body parser — NOT a raw-body or JSON parser — and pass the parsed { json: '...' } object to processWebhook().

  • Respond with the literal text Hello API Event Received (HTTP 200) after processWebhook() succeeds — Dropbox Sign treats any other response body as a failed delivery, retries, and eventually disables the callback.

  • Live sends only — there is no test-mode switch. The bond never sends test_mode=1, so every request is a real (billable) signature request; free/trial accounts get a 4xx on send, and signers receive real emails — use addresses you control in development.

  • Requires HELLOSIGN_API_KEY (read lazily at call time; never echoed into error messages). A missing key throws at first use, not at import.

E2E Tests

Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:

  • [ ] The send-for-signature flow creates a real request: picking a document and adding signer(s) in the UI calls createSignatureRequest, the app persists the returned SignatureRequest.id on its record, and the document shows as awaiting_signatures — NOT marked signed at creation.
  • [ ] The signer invitation actually leaves the app. The sandbox CAPTURES the outbound vendor invitation instead of emailing — read it with the read_activity tool (filter type 'email'); the signing link is in its payload. Never mock the flow or expect a real inbox.
  • [ ] COUNTERPARTY (the signing itself completes out-of-band on the vendor's hosted site, which can't be driven in-sandbox): verify completion against the app's OWN stored envelope state — deliver a signature_request_all_signed event to the webhook endpoint (or poll getSignatureRequest) and confirm the document flips awaiting_signaturessigned and the signer flips pendingsigned. Observe the transition, never guess it.
  • [ ] The signed PDF is retrievable only after completion: getSignedDocument returns the document once status is signed, and the UI download is gated on that status (unavailable/denied while the request is still awaiting signatures).
  • [ ] processWebhook rejects a forged callback — a bad signature THROWS and becomes a 4xx with no state change; a type: 'unknown' event is ignored (2xx).
  • [ ] AUTHORIZATION — only the request owner / a party to the document can view its status or download the signed PDF; no endpoint lets a caller fetch or act on someone else's SignatureRequest.id by guessing it.