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-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: '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 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 support@formshive.com.
Formshive Submit - Making form submissions robust and reliable. ✨