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

@memberjunction/actions-bizapps-formbuilders

v5.27.0

Published

Form builder and survey platform integration actions for MemberJunction

Downloads

7,036

Readme

@memberjunction/actions-bizapps-formbuilders

Form builder and survey platform integration actions for MemberJunction. This package provides a unified interface across four major form/survey platforms, enabling AI agents, workflows, and applications to programmatically retrieve responses, analyze submissions, and manage forms through the MemberJunction Actions framework.

This package is part of the BizApps Actions collection within the broader MemberJunction Actions Framework. For core action architecture, design philosophy, and when to use actions versus direct code, see the Actions CLAUDE.md.

Architecture

The package follows a three-tier class hierarchy: a shared base class providing common form operations, provider-specific base classes handling API authentication and data normalization, and individual action classes implementing specific operations.

graph TD
    subgraph Framework["Actions Framework"]
        BA["BaseAction<br/>@memberjunction/actions"]
    end

    subgraph Base["Shared Base Layer"]
        BFBA["BaseFormBuilderAction<br/>Credential management, CSV export,<br/>statistics helpers, response normalization"]
    end

    subgraph Providers["Provider Base Classes"]
        TF["TypeformBaseAction<br/>Bearer token auth<br/>Axios + rate limiting"]
        JF["JotFormBaseAction<br/>API key (query param)<br/>Regional endpoints"]
        SM["SurveyMonkeyBaseAction<br/>OAuth 2.0 Bearer<br/>Paginated responses"]
        GF["GoogleFormsBaseAction<br/>OAuth 2.0 Bearer<br/>Read-only API"]
    end

    subgraph Actions["Action Classes (34 total)"]
        TFA["Typeform Actions (10)"]
        JFA["JotForm Actions (8)"]
        SMA["SurveyMonkey Actions (8)"]
        GFA["Google Forms Actions (4)"]
    end

    subgraph Shared["Shared Utilities"]
        FCP["FileContentProcessor<br/>PDF, Excel, Word,<br/>image extraction"]
    end

    BA --> BFBA
    BFBA --> TF
    BFBA --> JF
    BFBA --> SM
    BFBA --> GF
    TF --> TFA
    JF --> JFA
    SM --> SMA
    GF --> GFA
    TFA -.-> FCP

    style Framework fill:#64748b,stroke:#475569,color:#fff
    style Base fill:#2d6a9f,stroke:#1a4971,color:#fff
    style TF fill:#7c5295,stroke:#563a6b,color:#fff
    style JF fill:#7c5295,stroke:#563a6b,color:#fff
    style SM fill:#7c5295,stroke:#563a6b,color:#fff
    style GF fill:#7c5295,stroke:#563a6b,color:#fff
    style TFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style JFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style SMA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style GFA fill:#2d8659,stroke:#1a5c3a,color:#fff
    style FCP fill:#b8762f,stroke:#8a5722,color:#fff

Supported Platforms

| Platform | Auth Method | Actions | Capabilities | |----------|------------|---------|-------------| | Typeform | Bearer token (personal access token) | 10 | Full CRUD: responses, forms, file content | | JotForm | API key (query parameter) | 8 | Full CRUD: submissions, forms | | SurveyMonkey | OAuth 2.0 Bearer token | 8 | Full CRUD: responses, surveys, collectors | | Google Forms | OAuth 2.0 Bearer token | 4 | Read-only: responses, form details |

Installation

npm install @memberjunction/actions-bizapps-formbuilders

This package is part of the MemberJunction monorepo. When working within the monorepo, add the dependency to your package's package.json and run npm install at the repository root.

Actions Reference

Typeform Actions (10)

| Action Class | Registration Name | Description | |-------------|------------------|-------------| | GetTypeformResponsesAction | GetTypeformResponsesAction | Retrieve responses with filtering, pagination, and auto-paginate support | | GetSingleTypeformResponseAction | GetSingleTypeformResponseAction | Retrieve a specific response by token | | GetTypeformStatisticsAction | GetTypeformStatisticsAction | Calculate aggregate analytics (completion rates, distributions, top answers) | | ExportTypeformCSVAction | ExportTypeformCSVAction | Export responses to CSV format with optional metadata | | WatchNewTypeformResponsesAction | WatchNewTypeformResponsesAction | Poll for new submissions since a given timestamp | | GetTypeformAction | GetTypeformAction | Retrieve complete form configuration and field definitions | | GetTypeformFormsAction | GetTypeformFormsAction | List all forms in a workspace | | TypeformGetFileContentAction | TypeformGetFileContentAction | Download and process file upload answers (PDF, Excel, Word, images) | | CreateTypeformAction | CreateTypeformAction | Create new forms programmatically with fields, settings, and logic | | UpdateTypeformAction | UpdateTypeformAction | Modify existing forms with safe merge mode |

JotForm Actions (8)

| Action Class | Registration Name | Description | |-------------|------------------|-------------| | GetJotFormSubmissionsAction | GetJotFormSubmissionsAction | Retrieve submissions with filtering and pagination | | GetSingleJotFormSubmissionAction | GetSingleJotFormSubmissionAction | Retrieve a specific submission by ID | | GetJotFormStatisticsAction | GetJotFormStatisticsAction | Calculate aggregate analytics from submissions | | ExportJotFormCSVAction | ExportJotFormCSVAction | Export submissions to CSV format | | WatchNewJotFormSubmissionsAction | WatchNewJotFormSubmissionsAction | Poll for new submissions since a given timestamp | | GetJotFormAction | GetJotFormAction | Retrieve form details and questions | | CreateJotFormAction | CreateJotFormAction | Create new forms with questions and properties | | UpdateJotFormAction | UpdateJotFormAction | Modify existing form configuration |

SurveyMonkey Actions (8)

| Action Class | Registration Name | Description | |-------------|------------------|-------------| | GetSurveyMonkeyResponsesAction | GetSurveyMonkeyResponsesAction | Retrieve responses with date range and status filtering | | GetSingleSurveyMonkeyResponseAction | GetSingleSurveyMonkeyResponseAction | Retrieve a specific response by ID | | GetSurveyMonkeyStatisticsAction | GetSurveyMonkeyStatisticsAction | Calculate aggregate analytics from responses | | ExportSurveyMonkeyCSVAction | ExportSurveyMonkeyCSVAction | Export responses to CSV format | | WatchNewSurveyMonkeyResponsesAction | WatchNewSurveyMonkeyResponsesAction | Poll for new responses since a given timestamp | | GetSurveyMonkeyAction | GetSurveyMonkeyAction | Retrieve survey details and configuration | | CreateSurveyMonkeyAction | CreateSurveyMonkeyAction | Create new surveys with pages and questions | | UpdateSurveyMonkeyAction | UpdateSurveyMonkeyAction | Modify existing survey properties |

Google Forms Actions (4)

| Action Class | Registration Name | Description | |-------------|------------------|-------------| | GetSingleGoogleFormsResponseAction | GetSingleGoogleFormsResponseAction | Retrieve a specific response by ID | | GetGoogleFormsStatisticsAction | GetGoogleFormsStatisticsAction | Calculate aggregate analytics from responses | | ExportGoogleFormsCSVAction | ExportGoogleFormsCSVAction | Export responses to CSV format | | GetGoogleFormAction | GetGoogleFormAction | Retrieve form details, questions, and quiz settings |

Note: Google Forms API is read-only. There are no endpoints for creating or updating forms programmatically.

Common Data Model

All providers normalize their responses into a shared FormResponse interface, enabling provider-agnostic processing downstream.

classDiagram
    class FormResponse {
        +string responseId
        +string formId
        +Date submittedAt
        +boolean completed
        +FormAnswer[] answerDetails
        +Record answers
        +metadata
        +calculatedFields
        +hiddenFields
    }

    class FormAnswer {
        +string fieldId
        +string fieldType
        +string question
        +answer
        +string[] choices
    }

    class FormStatistics {
        +number totalResponses
        +number completedResponses
        +number partialResponses
        +number completionRate
        +number averageCompletionTime
        +Record responsesByDate
        +topAnswers
    }

    FormResponse --> FormAnswer : answerDetails

    style FormResponse fill:#2d6a9f,stroke:#1a4971,color:#fff
    style FormAnswer fill:#7c5295,stroke:#563a6b,color:#fff
    style FormStatistics fill:#2d8659,stroke:#1a5c3a,color:#fff

Authentication and Credentials

All form builder actions use a secure credential resolution chain. Credentials are never passed as direct action parameters; instead, they are resolved from environment variables or the MemberJunction Company Integrations entity.

Credential Resolution Order

  1. Environment variables (company-specific): BIZAPPS_{PROVIDER}_{COMPANY_ID}_{CREDENTIAL_TYPE}
  2. Environment variables (default): BIZAPPS_{PROVIDER}_{CREDENTIAL_TYPE}
  3. Database (Company Integrations entity): AccessToken, APIKey fields

Environment Variable Examples

# Typeform - Personal access token
export BIZAPPS_TYPEFORM_API_TOKEN=tfp_your_token_here
export BIZAPPS_TYPEFORM_12345_API_TOKEN=tfp_company_specific_token

# JotForm - API key
export BIZAPPS_JOTFORM_API_KEY=your_jotform_api_key
export BIZAPPS_JOTFORM_12345_API_KEY=company_specific_key

# SurveyMonkey - OAuth 2.0 access token
export BIZAPPS_SURVEYMONKEY_ACCESS_TOKEN=your_oauth_token

# Google Forms - OAuth 2.0 access token
export BIZAPPS_GOOGLE_FORMS_ACCESS_TOKEN=your_google_oauth_token

# OAuth2 client credentials (for token refresh)
export BIZAPPS_TYPEFORM_CLIENT_ID=your_client_id
export BIZAPPS_TYPEFORM_CLIENT_SECRET=your_client_secret

Database Configuration

Store credentials in the Company Integrations entity linked to the appropriate Integration record:

-- 1. Create Integration record for the platform
INSERT INTO Integration (Name, Description, NavigationBaseURL, ClassName)
VALUES ('Typeform', 'Typeform form builder', 'https://api.typeform.com', 'TypeformIntegration');

-- 2. Link to Company with credentials
INSERT INTO CompanyIntegration (CompanyID, IntegrationID, AccessToken, IsActive)
VALUES (@CompanyID, @IntegrationID, 'tfp_your_token', 1);

Usage Examples

Retrieving Form Responses

import { ActionEngineServer } from '@memberjunction/actions';

const engine = ActionEngineServer.Instance;

// Get Typeform responses with date filtering
const result = await engine.RunAction({
    Action: engine.Actions.find(a => a.Name === 'Get Typeform Responses'),
    Params: [
        { Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
        { Name: 'FormID', Type: 'Input', Value: 'abc123' },
        { Name: 'Since', Type: 'Input', Value: '2024-01-01T00:00:00Z' },
        { Name: 'GetAllPages', Type: 'Input', Value: true }
    ],
    ContextUser: currentUser
});

if (result.Success) {
    const responses = result.Params.find(p => p.Name === 'Responses')?.Value;
    console.log(`Retrieved ${responses.length} responses`);
}

Exporting Responses to CSV

const exportResult = await engine.RunAction({
    Action: engine.Actions.find(a => a.Name === 'Export JotForm Responses to CSV'),
    Params: [
        { Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
        { Name: 'FormID', Type: 'Input', Value: '240123456789' },
        { Name: 'IncludeMetadata', Type: 'Input', Value: true }
    ],
    ContextUser: currentUser
});

const csvData = exportResult.Params.find(p => p.Name === 'CSVData')?.Value;

Creating a Form Programmatically

const createResult = await engine.RunAction({
    Action: engine.Actions.find(a => a.Name === 'Create Typeform'),
    Params: [
        { Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
        { Name: 'Title', Type: 'Input', Value: 'Customer Feedback Survey' },
        {
            Name: 'Fields', Type: 'Input', Value: [
                {
                    type: 'short_text',
                    title: 'What is your name?',
                    ref: 'name'
                },
                {
                    type: 'rating',
                    title: 'How satisfied are you?',
                    ref: 'satisfaction',
                    properties: { steps: 5, shape: 'star' }
                },
                {
                    type: 'long_text',
                    title: 'Any additional feedback?',
                    ref: 'feedback'
                }
            ]
        }
    ],
    ContextUser: currentUser
});

const formUrl = createResult.Params.find(p => p.Name === 'FormURL')?.Value;

Watching for New Responses

// Poll for new SurveyMonkey responses
const watchResult = await engine.RunAction({
    Action: engine.Actions.find(a => a.Name === 'Watch for New SurveyMonkey Responses'),
    Params: [
        { Name: 'CompanyID', Type: 'Input', Value: 'company-123' },
        { Name: 'SurveyID', Type: 'Input', Value: 'survey-456' },
        { Name: 'LastCheckedTimestamp', Type: 'Input', Value: '2024-06-01T00:00:00Z' },
        { Name: 'OnlyCompleted', Type: 'Input', Value: true }
    ],
    ContextUser: currentUser
});

const hasNew = watchResult.Params.find(p => p.Name === 'HasNewResponses')?.Value;
const newResponses = watchResult.Params.find(p => p.Name === 'NewResponses')?.Value;

File Content Processing

The package includes a FileContentProcessor utility used by the Typeform GetFileContentAction to intelligently extract content from file upload answers. It supports multiple file formats:

| Format | Processing | Output | |--------|-----------|--------| | PDF | Text extraction via pdf-parse | Plain text | | Excel (.xlsx, .xls) | Sheet parsing via exceljs | Structured JSON | | Word (.docx, .doc) | Text extraction via mammoth | Plain text | | Images | Base64 encoding | Base64 string (for LLM vision) | | Text/JSON/XML/CSV | UTF-8 decoding | Plain text | | Other binary | Base64 encoding | Base64 string |

Error Handling

All actions return consistent error information through the ActionResultSimple interface:

| Result Code | Description | |------------|-------------| | SUCCESS | Operation completed successfully | | MISSING_FORM_ID | Required FormID parameter was not provided | | MISSING_API_TOKEN | No API credentials could be resolved | | MISSING_CONTEXT_USER | Context user is required for credential lookup | | ERROR | General error (check Message for details) |

Each provider automatically handles platform-specific HTTP errors:

  • 401 - Invalid or expired API token
  • 403 - Insufficient permissions / scope
  • 404 - Form or response not found
  • 429 - Rate limit exceeded (automatic retry with exponential backoff)

Rate Limiting

All providers include built-in rate limit handling with automatic retry:

  • Respects Retry-After headers when provided
  • Falls back to 60-second wait when no header is present
  • Adds 100ms delays between pagination requests to avoid hitting limits
  • JotForm: Regional endpoints (US, EU, HIPAA) for data residency compliance

Dependencies

| Package | Purpose | |---------|---------| | @memberjunction/actions | Action engine and BaseAction class | | @memberjunction/actions-base | ActionParam types and base interfaces | | @memberjunction/core | RunView, Metadata, UserInfo, logging | | @memberjunction/core-entities | CompanyIntegrationEntity for credential lookup | | @memberjunction/global | @RegisterClass decorator | | axios | HTTP client for all provider API calls | | exceljs | Excel file parsing in FileContentProcessor | | mammoth | Word document text extraction | | pdf-parse | PDF text extraction |

Related Packages

Adding a New Provider

To integrate a new form/survey platform:

  1. Create provider directory: src/providers/{platform}/
  2. Implement a provider base class extending BaseFormBuilderAction with:
    • formPlatform and integrationName properties
    • Axios instance with authentication and rate limit interceptors
    • API client methods for the provider's endpoints
    • Response normalization to the shared FormResponse interface
    • Provider-specific error handling
  3. Create individual action classes in src/providers/{platform}/actions/
  4. Export all classes from src/providers/{platform}/index.ts
  5. Add the provider export to src/index.ts