@gofranz/formshive-submit
v1.0.2
Published
JavaScript library for submitting forms to Formshive with retry logic, file support, and flexible HTTP client options
Maintainers
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-submitFor 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 issuesTIMEOUT_ERROR- Request timeoutVALIDATION_ERROR- Form validation failedFILE_TOO_LARGE- File exceeds size limitINVALID_FILE_TYPE- File type not allowedFORM_NOT_FOUND- Form ID not foundSERVER_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 errorsgetFieldErrors(error)- Get array of all field validation errorsgetFieldError(error, fieldName)- Get validation error for specific fieldhasFieldError(error, fieldName)- Check if specific field has errorgetErrorFieldNames(error)- Get names of all fields with errorsformatFieldErrors(error)- Get simple object mapping field names to error messagescreateFieldErrorHelpers(error)- Create helper object for UI integrationgetValidationErrorSummary(error)- Get human-readable error summaryhasErrorCode(error, code)- Check if any field has specific error codegetErrorsByCode(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. ✨
