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

@gofranz/formshive-submit

v1.0.2

Published

JavaScript library for submitting forms to Formshive with retry logic, file support, and flexible HTTP client options

Readme

Formshive Submit

A robust JavaScript/TypeScript library for submitting forms to Formshive with advanced features including retry logic, file uploads, progress tracking, and flexible HTTP client support.

Features

  • 🚀 Easy to use - Simple API for form submissions
  • 🔄 Smart retry logic - Exponential backoff with configurable settings
  • 📁 File upload support - Handle single and multiple file uploads with progress tracking
  • 🔌 Flexible HTTP clients - Works with both fetch and axios
  • 💪 TypeScript support - Fully typed for better development experience
  • 🎯 Callback system - Success, error, retry, and progress callbacks
  • 🔧 Configurable - Extensive configuration options for different use cases
  • 🌐 Universal - Works in browser and Node.js environments
  • Lightweight - Minimal dependencies, tree-shakeable

Installation

npm install @gofranz/formshive-submit
# or
yarn add @gofranz/formshive-submit
# or
pnpm add @gofranz/formshive-submit

For browser usage via CDN:

<script src="https://unpkg.com/@gofranz/formshive-submit/dist/formshive-submit.min.js"></script>

Quick Start

Basic Form Submission

import { submitFormSimple } from '@gofranz/formshive-submit';

// Simple form submission
const response = await submitFormSimple('your-form-id', {
    name: 'John Doe',
    email: '[email protected]',
    message: 'Hello from Formshive Submit!'
});

console.log('Form submitted successfully:', response);

With Error Handling

import { submitForm } from '@gofranz/formshive-submit';

try {
    const response = await submitForm({
        formId: 'your-form-id',
        data: {
            name: 'Jane Smith',
            email: '[email protected]',
            subject: 'Contact Form',
            message: 'This is a test message.'
        },
        callbacks: {
            onSuccess: (response) => {
                console.log('Success!', response);
            },
            onError: (error) => {
                console.error('Submission failed:', error);
            },
            onRetry: (attempt, maxAttempts) => {
                console.log(`Retrying... ${attempt}/${maxAttempts}`);
            }
        }
    });
} catch (error) {
    console.error('Final error:', error);
}

File Upload

Single File Upload

import { submitForm } from '@gofranz/formshive-submit';

const fileInput = document.getElementById('fileInput');
const formData = new FormData();

formData.append('name', 'John Doe');
formData.append('file', fileInput.files[0]);

const response = await submitForm({
    formId: 'file-upload-form',
    data: formData,
    callbacks: {
        onProgress: (percent, loaded, total) => {
            console.log(`Upload progress: ${percent}%`);
            document.getElementById('progress').style.width = percent + '%';
        }
    }
});

Multiple Files with Validation

import { submitForm } from '@gofranz/formshive-submit';

const files = document.getElementById('multipleFiles').files;
const formData = new FormData();

formData.append('title', 'Multiple File Upload');
for (let i = 0; i < files.length; i++) {
    formData.append(`file_${i}`, files[i]);
}

const response = await submitForm({
    formId: 'multi-file-form',
    data: formData,
    files: {
        maxFileSize: 10 * 1024 * 1024, // 10MB per file
        allowedTypes: ['image/jpeg', 'image/png', 'application/pdf'],
        trackProgress: true
    },
    callbacks: {
        onProgress: (percent) => updateProgressBar(percent)
    }
});

Configuration Options

Retry Configuration

import { submitForm, RetryPresets } from '@gofranz/formshive-submit';

const response = await submitForm({
    formId: 'your-form-id',
    data: { message: 'Hello' },
    retry: {
        maxAttempts: 5,
        baseDelay: 2000,      // 2 seconds
        maxDelay: 30000,      // 30 seconds max
        enableJitter: true,   // Add randomness to delays
        backoffMultiplier: 2  // Exponential backoff factor
    }
});

// Or use presets
const response2 = await submitForm({
    formId: 'your-form-id',
    data: { message: 'Hello' },
    retry: RetryPresets.patient() // More retries, longer delays
});

Using Axios Instead of Fetch

import axios from 'axios';
import { submitForm } from '@gofranz/formshive-submit';

// Option 1: Use string identifier
const response = await submitForm({
    formId: 'your-form-id',
    data: { message: 'Hello' },
    httpClient: 'axios' // Requires axios to be installed
});

// Option 2: Use custom axios instance
const customAxios = axios.create({
    timeout: 10000,
    headers: {
        'Custom-Header': 'value'
    }
});

const response2 = await submitForm({
    formId: 'your-form-id',
    data: { message: 'Hello' },
    httpClient: customAxios
});

Custom Endpoint and Headers

const response = await submitForm({
    formId: 'your-form-id',
    data: { message: 'Hello' },
    endpoint: 'https://your-custom-domain.com/api/v1',
    headers: {
        'Authorization': 'Bearer your-token',
        'Custom-Header': 'custom-value'
    },
    timeout: 15000 // 15 seconds
});

Advanced Usage

Form Validation

import { validateFormData, submitForm } from '@gofranz/formshive-submit';

const data = {
    name: '',
    email: 'invalid-email',
    message: 'Hello'
};

const validation = validateFormData(data);
if (!validation.isValid) {
    console.log('Validation errors:', validation.errors);
    console.log('Warnings:', validation.warnings);
    return;
}

const response = await submitForm({
    formId: 'validated-form',
    data: data
});

Reusable Form Submitter

import { FormSubmitter } from '@gofranz/formshive-submit';

// Create a submitter with default configuration
const submitter = new FormSubmitter({
    endpoint: 'https://api.myapp.com/v1',
    retry: {
        maxAttempts: 5,
        baseDelay: 1000
    },
    debug: true
});

// Submit multiple forms using the same configuration
const response1 = await submitter.submit('contact-form', {
    name: 'John',
    email: '[email protected]'
});

const response2 = await submitter.submit('feedback-form', {
    rating: 5,
    comment: 'Great service!'
});

// Test connection
const isConnected = await submitter.testConnection();
console.log('API is reachable:', isConnected);

Progress Tracking

import { submitForm, formatFileSize } from '@gofranz/formshive-submit';

const response = await submitForm({
    formId: 'upload-form',
    data: formData,
    callbacks: {
        onStart: () => {
            console.log('Upload starting...');
            showProgressBar(true);
        },
        onProgress: (percent, loaded, total) => {
            const loadedSize = formatFileSize(loaded);
            const totalSize = formatFileSize(total);
            console.log(`${percent}% - ${loadedSize}/${totalSize}`);
            updateProgress(percent);
        },
        onSuccess: (response) => {
            console.log('Upload complete!');
            hideProgressBar();
        },
        onError: (error) => {
            console.error('Upload failed:', error);
            showError(error.message);
        }
    }
});

Browser Usage (CDN)

<!DOCTYPE html>
<html>
<head>
    <title>Formshive Submit Example</title>
</head>
<body>
    <form id="myForm">
        <input type="text" name="name" placeholder="Name" required>
        <input type="email" name="email" placeholder="Email" required>
        <textarea name="message" placeholder="Message"></textarea>
        <input type="file" name="file" multiple>
        <button type="submit">Submit</button>
    </form>

    <script src="https://unpkg.com/@gofranz/formshive-submit/dist/formshive-submit.min.js"></script>
    <script>
        document.getElementById('myForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const formData = new FormData(e.target);
            
            try {
                const response = await FormshiveSubmit.submitForm({
                    formId: 'my-form-id',
                    data: formData,
                    callbacks: {
                        onSuccess: (response) => {
                            alert('Form submitted successfully!');
                        },
                        onError: (error) => {
                            alert('Error: ' + error.message);
                        }
                    }
                });
            } catch (error) {
                console.error('Submission error:', error);
            }
        });
    </script>
</body>
</html>

API Reference

Functions

submitForm(options: FormshiveSubmitOptions): Promise<SubmitResponse>

Main form submission function with full configuration options.

submitFormSimple(formId: string, data: Record<string, any> | FormData, options?: Partial<FormshiveSubmitOptions>): Promise<SubmitResponse>

Simplified submission function for basic use cases.

validateFormData(data: Record<string, any> | FormData): ValidationResult

Validates form data before submission.

Classes

FormSubmitter

Reusable form submitter with configurable defaults.

const submitter = new FormSubmitter(defaultOptions);
await submitter.submit(formId, data, overrideOptions);

Types

FormshiveSubmitOptions

interface FormshiveSubmitOptions {
    formId: string;                    // Required: Formshive form ID
    data: Record<string, any> | FormData; // Required: Form data
    endpoint?: string;                 // API endpoint (default: api.formshive.com)
    httpClient?: HttpClient;           // 'fetch', 'axios', or axios instance
    retry?: RetryConfig;               // Retry configuration
    files?: FileConfig;                // File upload configuration  
    callbacks?: FormshiveCallbacks;    // Success/error/progress callbacks
    headers?: Record<string, string>;  // Additional HTTP headers
    timeout?: number;                  // Request timeout in milliseconds
    debug?: boolean;                   // Enable debug logging
}

SubmitResponse

interface SubmitResponse {
    success: boolean;
    data?: any;
    statusCode: number;
    headers?: Record<string, string>;
    redirectUrl?: string;
    attempt: number;
    duration: number;
}

SubmitError

interface SubmitError extends Error {
    code: string;
    statusCode?: number;
    response?: any;
    attempt: number;
    isRetryable: boolean;
    originalError?: Error;
    fieldErrors?: FieldValidationError[];
    validationResponse?: FieldValidationErrorResponse;
}

Error Handling

The library provides detailed error information with specific error codes:

  • NETWORK_ERROR - Network connectivity issues
  • TIMEOUT_ERROR - Request timeout
  • VALIDATION_ERROR - Form validation failed
  • FILE_TOO_LARGE - File exceeds size limit
  • INVALID_FILE_TYPE - File type not allowed
  • FORM_NOT_FOUND - Form ID not found
  • SERVER_ERROR - Server-side error (5xx)
  • RATE_LIMITED - Too many requests (429)
try {
    const response = await submitForm(options);
} catch (error) {
    switch (error.code) {
        case 'FORM_NOT_FOUND':
            console.error('Form not found. Check your form ID.');
            break;
        case 'FILE_TOO_LARGE':
            console.error('File is too large. Please choose a smaller file.');
            break;
        case 'NETWORK_ERROR':
            console.error('Network error. Please check your connection.');
            break;
        default:
            console.error('Unexpected error:', error.message);
    }
}

Field Validation Errors

When form validation fails (400 Bad Request), Formshive returns structured field-level validation errors that you can use to display specific error messages for each form field.

Checking for Field Validation Errors

import { submitForm, isFieldValidationError, getFieldErrors } from '@gofranz/formshive-submit';

try {
    const response = await submitForm({
        formId: 'contact-form',
        data: {
            name: '',  // Missing required field
            email: 'invalid-email',  // Invalid format
            message: 'Hello'
        }
    });
} catch (error) {
    if (isFieldValidationError(error)) {
        console.log('Form has validation errors');
        const fieldErrors = getFieldErrors(error);
        
        fieldErrors.forEach(fieldError => {
            console.log(`Field: ${fieldError.field}`);
            console.log(`Error: ${fieldError.message}`);
            console.log(`Code: ${fieldError.code}`);
        });
    } else {
        console.error('Non-validation error:', error.message);
    }
}

Using Field Error Helpers for UI

The library provides helper functions to make it easy to display field errors in your forms:

import { createFieldErrorHelpers, submitForm } from '@gofranz/formshive-submit';

let currentError = null;

// Create helpers for easy UI integration
const errorHelpers = createFieldErrorHelpers(currentError);

// Check if a field has an error
if (errorHelpers.hasError('email')) {
    document.getElementById('email').classList.add('input-error');
}

// Get error message for a field
const emailErrorMsg = errorHelpers.getMessage('email');
if (emailErrorMsg) {
    document.getElementById('email-error').textContent = emailErrorMsg;
}

// Get CSS class for field error state
const fieldClass = errorHelpers.getFieldClass('email', 'has-error');
document.getElementById('email').className = fieldClass;

Complete Field Validation Example

import { 
    submitForm, 
    isFieldValidationError, 
    createFieldErrorHelpers, 
    getValidationErrorSummary 
} from '@gofranz/formshive-submit';

async function handleFormSubmit(formData) {
    let currentError = null;
    
    try {
        const response = await submitForm({
            formId: 'registration-form',
            data: formData
        });
        
        // Success - clear any previous errors
        clearFieldErrors();
        showSuccessMessage();
        
    } catch (error) {
        currentError = error;
        
        if (isFieldValidationError(error)) {
            // Handle field-specific validation errors
            displayFieldErrors(error);
            
            // Show general validation summary
            const summary = getValidationErrorSummary(error);
            showErrorMessage(summary);
            
        } else {
            // Handle other types of errors
            showErrorMessage(error.message || 'An unexpected error occurred');
        }
    }
}

function displayFieldErrors(error) {
    const helpers = createFieldErrorHelpers(error, 'field-error');
    const fieldNames = ['name', 'email', 'phone', 'message'];
    
    fieldNames.forEach(fieldName => {
        const input = document.getElementById(fieldName);
        const errorDiv = document.getElementById(`${fieldName}-error`);
        
        if (helpers.hasError(fieldName)) {
            // Add error styling
            input.classList.add('field-error');
            
            // Show error message
            errorDiv.textContent = helpers.getMessage(fieldName);
            errorDiv.style.display = 'block';
        } else {
            // Clear error state
            input.classList.remove('field-error');
            errorDiv.style.display = 'none';
        }
    });
}

Field Validation Error Types

interface FieldValidationError {
    field: string;                    // Field name (e.g., 'email')
    code: string;                     // Error code (e.g., 'required', 'invalid_format')
    message: string;                  // User-friendly error message
    params: Record<string, any>;      // Additional error parameters
}

interface FieldValidationErrorResponse {
    error: string;                    // Always 'validation_error'
    action?: string;                  // Optional action hint
    message: string;                  // General validation error message
    errors: FieldValidationError[];   // Array of field-specific errors
}

Available Field Error Utility Functions

The library exports many utility functions for working with field validation errors:

  • isFieldValidationError(error) - Check if error contains field validation errors
  • getFieldErrors(error) - Get array of all field validation errors
  • getFieldError(error, fieldName) - Get validation error for specific field
  • hasFieldError(error, fieldName) - Check if specific field has error
  • getErrorFieldNames(error) - Get names of all fields with errors
  • formatFieldErrors(error) - Get simple object mapping field names to error messages
  • createFieldErrorHelpers(error) - Create helper object for UI integration
  • getValidationErrorSummary(error) - Get human-readable error summary
  • hasErrorCode(error, code) - Check if any field has specific error code
  • getErrorsByCode(error, code) - Get all errors with specific code

Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements.

License

MIT License - see LICENSE file for details.

Support

For issues and questions, please visit our GitHub repository or contact support at [email protected].


Formshive Submit - Making form submissions robust and reliable. ✨