@bhandari88/form-builder-core
v1.1.1
Published
A powerful, secure, and fast form builder with S3 syncing, supporting large forms, subforms, sections, and subsections
Maintainers
Readme
Form Builder
A powerful, secure, and fast form builder npm package with S3 syncing, supporting large forms, subforms, sections, and subsections. All form data is stored as JSON, making it easy to customize and integrate. Now includes a full-featured Events Calendar!
Features
- ✅ Large Forms Support - Handle complex forms with hundreds of fields
- ✅ Hierarchical Structure - Forms → SubForms → Sections → SubSections → Fields
- ✅ JSON-Based - All form definitions stored as JSON
- ✅ Events Calendar - Full-featured calendar with event management, recurring events, and multiple views
- ✅ S3 Bucket Syncing - Automatic syncing with AWS S3 (default enabled)
- ✅ Fully Secure - Encryption support for sensitive data
- ✅ Fast Performance - Optimized with memoization, lazy loading, and batching
- ✅ Customizable - Easy to customize UI and behavior
- ✅ React Components - Ready-to-use React components for forms and calendar
- ✅ Validation - Built-in validation engine with custom rules
- ✅ Conditional Logic - Show/hide fields, sections based on conditions
- ✅ TypeScript - Full TypeScript support
Installation
npm install @bhandari88/form-builder-coreRequirements
Frontend (React)
- React: ^18.0.0 or ^19.0.0 (optional peer dependency)
- React DOM: ^18.0.0 or ^19.0.0 (optional peer dependency)
- Works in browser environments (React components only)
- S3 syncing features are disabled in frontend (use backend API instead)
Backend (Node.js)
- Node.js: >=16.0.0
- TypeScript: ^5.3.3 (for development)
- Full S3 syncing support available
- AWS SDK v3 compatible
Package Compatibility
- ✅ React 18.x
- ✅ React 19.x
- ✅ Node.js 16.x, 18.x, 20.x, 22.x
- ✅ TypeScript 5.x
- ✅ CommonJS and ES Modules
⚠️ Security Notice
IMPORTANT: Never use AWS credentials in frontend/client-side code. AWS credentials should only be used in secure server-side environments.
- ✅ DO: Use S3 syncing in Node.js backend/server environments
- ✅ DO: Use environment variables on the server
- ✅ DO: Use IAM roles when running on AWS infrastructure
- ❌ DON'T: Put AWS credentials in React components or browser code
- ❌ DON'T: Commit credentials to version control
- ❌ DON'T: Expose credentials in client-side bundles
For frontend usage, create API endpoints on your backend to handle S3 operations securely.
Quick Start
Basic Usage
import { FormBuilder } from '@bhandari88/form-builder-core';
// Create a new form builder
const formBuilder = new FormBuilder();
// Add a section
const section = formBuilder.addSection({
title: 'Personal Information',
description: 'Enter your personal details',
fields: []
});
// Add fields to the section
formBuilder.addField(section.id, {
name: 'firstName',
label: 'First Name',
type: 'text',
required: true,
validation: [
{ type: 'required', message: 'First name is required' },
{ type: 'min', value: 2, message: 'First name must be at least 2 characters' }
]
});
formBuilder.addField(section.id, {
name: 'email',
label: 'Email Address',
type: 'email',
required: true,
validation: [
{ type: 'required' },
{ type: 'email' }
]
});
// Get form as JSON
const formJSON = formBuilder.toJSON();
console.log(formJSON);With S3 Syncing (Server-Side Only)
⚠️ This should only be used in Node.js backend/server environments, never in frontend code.
import { FormBuilder } from '@bhandari88/form-builder-core';
// Server-side only - use environment variables
const formBuilder = new FormBuilder(undefined, {
enableS3Sync: true,
s3Config: {
bucket: process.env.AWS_S3_BUCKET!,
region: process.env.AWS_REGION || 'us-east-1',
// Use environment variables - never hardcode credentials
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
encryptionKey: process.env.ENCRYPTION_KEY, // Optional
autoSave: true,
autoSaveInterval: 30000 // 30 seconds
});
// Create and save form
const section = formBuilder.addSection({
title: 'Contact Information',
fields: []
});
formBuilder.addField(section.id, {
name: 'phone',
label: 'Phone Number',
type: 'tel',
required: true
});
// Save to S3 (server-side only)
await formBuilder.save();
// Load from S3 (server-side only)
await formBuilder.load(formId);React Integration
For frontend usage, disable S3 sync and handle persistence through your backend API.
import React from 'react';
import { FormBuilder } from '@bhandari88/form-builder-core';
import { FormBuilderProvider, FormRenderer, useFormBuilder } from '@bhandari88/form-builder-core/react';
function MyForm() {
// Frontend: Don't use S3 sync - handle through backend API
const formBuilder = new FormBuilder(undefined, {
enableS3Sync: false, // Disabled for frontend
});
const handleSubmit = async (values: any) => {
// Send form data to your backend API
await fetch('/api/forms', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(values),
});
};
return (
<FormBuilderProvider formBuilder={formBuilder} onSubmit={handleSubmit}>
<FormRenderer />
<SubmitButton />
</FormBuilderProvider>
);
}
function SubmitButton() {
const { submit, isValid, isSubmitting } = useFormBuilder();
return (
<button
onClick={submit}
disabled={!isValid || isSubmitting}
>
{isSubmitting ? 'Submitting...' : 'Submit'}
</button>
);
}Backend API Example (Node.js/Express)
Proper server-side implementation with S3 syncing:
// server/api/forms.ts
import express from 'express';
import { FormBuilder } from '@bhandari88/form-builder-core';
const router = express.Router();
// Create form builder with S3 sync (server-side only)
const formBuilder = new FormBuilder(undefined, {
enableS3Sync: true,
s3Config: {
bucket: process.env.AWS_S3_BUCKET!,
region: process.env.AWS_REGION || 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
encryptionKey: process.env.ENCRYPTION_KEY,
});
// Save form endpoint
router.post('/save', async (req, res) => {
try {
await formBuilder.save();
res.json({ success: true, formId: formBuilder.getFormData().id });
} catch (error) {
res.status(500).json({ error: 'Failed to save form' });
}
});
// Load form endpoint
router.get('/:formId', async (req, res) => {
try {
await formBuilder.load(req.params.formId);
res.json(formBuilder.getFormData());
} catch (error) {
res.status(404).json({ error: 'Form not found' });
}
});
export default router;Advanced Features
SubForms
// Add a subform
const subForm = formBuilder.addSubForm({
title: 'Additional Information',
description: 'Optional details',
sections: []
});
// Add sections to subform
const subFormSection = formBuilder.getSubForm(subForm.id);
// Note: You'll need to manually add sections to subformsSections and SubSections
// Add a section
const section = formBuilder.addSection({
title: 'Main Section',
fields: []
});
// Add a subsection
const subSection = formBuilder.addSubSection(section.id, {
title: 'Sub Section',
fields: []
});
// Add field to subsection
formBuilder.addFieldToSubSection(section.id, subSection.id, {
name: 'subField',
label: 'Sub Field',
type: 'text'
});Conditional Fields
formBuilder.addField(section.id, {
name: 'showAdvanced',
label: 'Show Advanced Options',
type: 'checkbox'
});
formBuilder.addField(section.id, {
name: 'advancedOption',
label: 'Advanced Option',
type: 'text',
conditional: {
field: 'showAdvanced',
operator: 'equals',
value: true
}
});Custom Validation
formBuilder.addField(section.id, {
name: 'password',
label: 'Password',
type: 'password',
validation: [
{ type: 'required' },
{ type: 'min', value: 8, message: 'Password must be at least 8 characters' },
{
type: 'custom',
validator: (value) => /[A-Z]/.test(value) && /[0-9]/.test(value),
message: 'Password must contain uppercase letter and number'
}
]
});Form Validation
const values = {
firstName: 'John',
email: '[email protected]'
};
// Validate form
const errors = formBuilder.validate(values);
console.log(errors);
// Check if valid
const isValid = formBuilder.isValid(values);API Reference
FormBuilder Class
Constructor
new FormBuilder(formData?: FormBuilderData, options?: FormBuilderOptions)Methods
addSection(section)- Add a new sectionupdateSection(sectionId, updates)- Update a sectionremoveSection(sectionId)- Remove a sectiongetSection(sectionId)- Get a section by IDaddSubSection(sectionId, subSection)- Add a subsectionaddField(sectionId, field)- Add a field to a sectionaddFieldToSubSection(sectionId, subSectionId, field)- Add a field to a subsectionupdateField(fieldId, updates)- Update a fieldremoveField(fieldId)- Remove a fieldgetAllFields()- Get all fields from the formaddSubForm(subForm)- Add a subformvalidate(values)- Validate form valuesisValid(values)- Check if form is validsave()- Save form to S3load(formId?)- Load form from S3sync()- Sync form with S3toJSON()- Get form as JSON stringgetFormData()- Get form data object
Field Types
text- Text inputtextarea- Multi-line textemail- Email inputnumber- Number inputpassword- Password inputdate- Date pickerdatetime- Date and time pickertime- Time pickerselect- Dropdown selectmultiselect- Multi-select dropdownradio- Radio buttonscheckbox- Checkboxfile- File uploadimage- Image uploadcolor- Color pickerrange- Range sliderurl- URL inputtel- Telephone inputhidden- Hidden field
Validation Rules
required- Field is requiredmin- Minimum value/lengthmax- Maximum value/lengthpattern- Regular expression patternemail- Email format validationurl- URL format validationcustom- Custom validator function
Security
⚠️ Critical Security Guidelines
Never Use AWS Credentials in Frontend Code
- ❌ DON'T: Use S3 sync in React components, browser code, or client-side JavaScript
- ✅ DO: Use S3 sync only in Node.js backend/server environments
- ✅ DO: Create API endpoints on your backend to handle S3 operations
Credential Management
- ✅ DO: Use environment variables on the server
- ✅ DO: Use IAM roles when running on AWS infrastructure (EC2, Lambda, etc.)
- ✅ DO: Use AWS Secrets Manager or similar services for production
- ❌ DON'T: Hardcode credentials in source code
- ❌ DON'T: Commit credentials to version control
- ❌ DON'T: Expose credentials in client-side bundles or environment variables prefixed with
REACT_APP_orNEXT_PUBLIC_
Data Protection
- Encryption: Optional AES-256-GCM encryption for S3 data
- Input Validation: All inputs are validated before processing
- Type Safety: Full TypeScript support prevents type errors
Best Practices
- Use least-privilege IAM policies for S3 access
- Enable S3 bucket encryption at rest
- Use HTTPS for all API communications
- Implement proper authentication/authorization for form access
Performance
- Memoization: Expensive computations are cached
- Lazy Loading: Only visible fields are processed
- Batching: Updates are batched to reduce re-renders
- Debouncing: Form updates are debounced
- Throttling: S3 sync operations are throttled
Events Calendar
The package includes a full-featured events calendar system that can work independently or be integrated with forms.
Basic Calendar Usage
import { EventsCalendar } from '@bhandari88/form-builder-core';
// Create a new calendar
const calendar = new EventsCalendar();
// Add an event
calendar.addEvent({
title: 'Team Meeting',
description: 'Weekly team sync',
startDate: new Date('2024-01-15T10:00:00').toISOString(),
endDate: new Date('2024-01-15T11:00:00').toISOString(),
startTime: '10:00',
endTime: '11:00',
location: 'Conference Room A',
color: '#3788d8',
});
// Get events for a date
const events = calendar.getEventsForDate('2024-01-15');
// Get events in a date range
const rangeEvents = calendar.getEventsInRange('2024-01-01', '2024-01-31');Recurring Events
calendar.addEvent({
title: 'Daily Standup',
startDate: new Date('2024-01-16T09:00:00').toISOString(),
startTime: '09:00',
endTime: '09:30',
recurrence: {
frequency: 'daily',
interval: 1,
count: 30, // 30 occurrences
byDay: ['MO', 'TU', 'WE', 'TH', 'FR'], // Weekdays only
},
});React Calendar Components
import { EventsCalendar } from '@bhandari88/form-builder-core';
import { CalendarProvider, CalendarView, EventForm, useCalendar } from '@bhandari88/form-builder-core/react';
function MyCalendar() {
const calendar = new EventsCalendar();
return (
<CalendarProvider calendar={calendar}>
<CalendarView
events={calendar.getAllEvents()}
onEventClick={(event) => console.log('Event clicked:', event)}
onDateClick={(date) => console.log('Date clicked:', date)}
onEventCreate={(date) => console.log('Create event on:', date)}
/>
</CalendarProvider>
);
}Calendar with S3 Syncing (Server-Side Only)
const calendar = new EventsCalendar(undefined, {
enableS3Sync: true,
s3Config: {
bucket: process.env.AWS_S3_BUCKET!,
region: process.env.AWS_REGION || 'us-east-1',
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
},
autoSave: true,
});
// Save to S3
await calendar.save();
// Load from S3
await calendar.load(calendarId);Calendar Features
- Multiple Views: Month, Week, Day, and Agenda views
- Event Management: Create, update, delete events
- Recurring Events: Support for daily, weekly, monthly, yearly recurrence
- Event Properties: Title, description, location, attendees, colors, reminders
- Date Range Queries: Get events for specific dates or ranges
- S3 Integration: Sync calendar data to S3 (server-side only)
- React Components: Ready-to-use calendar UI components
Examples
See the examples/ directory for more examples:
- Basic form creation
- S3 syncing
- React integration
- Conditional logic
- Custom validation
- Large forms handling
- Calendar basic usage
- Calendar React integration
- Calendar with S3 syncing
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
