JSPM

@gofranz/formshive-submit

1.0.4
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 6
    • Score
      100M100P100Q78696F
    • License MIT

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

    Package Exports

    • @gofranz/formshive-submit
    • @gofranz/formshive-submit/dist/formshive-submit.esm.js
    • @gofranz/formshive-submit/dist/formshive-submit.js

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@gofranz/formshive-submit) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    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: 'john@example.com',
        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: 'jane@example.com',
                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: 'john@example.com'
    });
    
    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 support@formshive.com.


    Formshive Submit - Making form submissions robust and reliable. ✨