bookingjs
v0.1.6
Published
A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling
Maintainers
Readme
BookingJS
A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling. Built following the LeagueJS architecture pattern, BookingJS provides a class-based approach for direct manipulation of booking data with full TypeScript support and cross-environment compatibility.
Features
- Framework Agnostic: Works with React, Vue, Angular, and vanilla JavaScript
- TypeScript Support: Full type definitions included
- Dual Module Support: ES Modules and CommonJS builds
- Real-time Availability: Advanced availability checking and conflict resolution
- Audit Logging: Complete audit trail for all booking operations
- Data Retention: Configurable cleanup policies for long-term data management
- Extensible Architecture: Easy to extend with custom booking types and validation rules
Installation
npm install bookingjsQuick Start
ES Modules
import { BookingSystem, Green, Rink, BookingType } from 'bookingjs';
// Create a booking system for your club
const bookingSystem = new BookingSystem({
club: 'your-club-id'
});
// Create a green with rinks
const green = new Green({
name: 'Main Green',
location: '123 Bowling St, Your City',
facilities: ['Changing Rooms', 'Car Park', 'Clubhouse']
});
// Add rinks to the green (up to 12 per green)
for (let i = 1; i <= 6; i++) {
green.addRink(new Rink({ number: i }));
}
// Add the green to the booking system
bookingSystem.addGreen(green);
// Create a booking
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
tomorrow.setHours(10, 0, 0, 0);
const booking = bookingSystem.createBooking({
memberId: 'member-123',
rinkId: green.rinks[0]._id,
bookingTypeId: 'regular',
date: tomorrow,
start: new Date(tomorrow),
end: new Date(tomorrow.getTime() + 2 * 60 * 60 * 1000), // 2 hours
notes: 'Team practice session'
}, 'member-123');
console.log('Booking created:', booking._id);CommonJS
const { BookingSystem, Green, Rink } = require('bookingjs');
// Same usage as aboveCore Classes
BookingSystem
The main class that orchestrates all booking operations.
const bookingSystem = new BookingSystem({
club: 'your-club-id',
settings: {
bookingRules: {
maxAdvanceBookingDays: 30,
minAdvanceBookingHours: 2,
maxBookingDuration: 180, // minutes
minBookingDuration: 60,
allowConcurrentBookings: false,
requireApproval: false
}
}
});
// Create bookings
const booking = bookingSystem.createBooking(bookingData, memberId);
// Modify bookings
bookingSystem.modifyBooking(bookingId, updates, memberId);
// Cancel bookings
bookingSystem.cancelBooking(bookingId, memberId);
// Check availability
const availability = bookingSystem.getAvailability(rinkId, date, duration);
// Get member bookings
const memberBookings = bookingSystem.getMemberBookings(memberId);
// Get system statistics
const stats = bookingSystem.getSystemStats();Green
Represents a bowling green containing multiple rinks.
const green = new Green({
name: 'Championship Green',
location: 'North Field',
facilities: ['Scoreboard', 'Seating', 'Lighting'],
allowedBookingTypes: ['regular', 'tournament'] // Optional restrictions
});
// Add rinks
green.addRink(new Rink({ number: 1 }));
// Get available rinks for a time period
const availableRinks = green.getAvailableRinks(
date,
startTime,
endTime,
existingBookings,
bookingTypeId
);
// Get utilization statistics
const stats = green.getUtilizationStats(allBookings, startDate, endDate);Rink
Represents an individual bookable rink within a green.
const rink = new Rink({
number: 1,
allowedBookingTypes: ['regular', 'maintenance'] // Optional restrictions
});
// Check availability
const isAvailable = rink.isAvailable(date, start, end, existingBookings);
// Validate a booking
rink.validateBooking(bookingTypeId, date, start, end, existingBookings);Booking
Represents a booking reservation.
const booking = new Booking({
memberId: 'member-123',
rinkId: 'rink-456',
bookingTypeId: 'regular',
date: new Date('2024-03-15'),
start: new Date('2024-03-15T10:00:00'),
end: new Date('2024-03-15T12:00:00'),
participants: ['member-123', 'member-456'],
notes: 'Weekly team practice'
});
// Update booking status
booking.updateStatus('confirmed');
// Add/remove participants
booking.addParticipant('member-789');
booking.removeParticipant('member-456');
// Check booking state
const isActive = booking.isActive();
const canModify = booking.canModify();
const duration = booking.getDuration(); // returns minutesBookingType
Defines types of bookings with visual styling and priorities.
const bookingType = new BookingType({
name: 'Tournament',
backgroundColor: '#9C27B0',
foregroundColor: '#FFFFFF',
description: 'Tournament or competition booking',
priority: 5
});
// Update booking type
bookingType.update({
priority: 10,
description: 'High priority tournament booking'
});
// Get default booking types
const defaults = BookingType.getDefaults();
// Returns: Regular, Maintenance, Tournament typesAdvanced Features
Availability Checking
// Get available time slots for a specific rink
const availability = bookingSystem.getAvailability(rinkId, date, durationMinutes);
// Check if a specific time slot is available
import { isTimeSlotAvailable } from 'bookingjs';
const isAvailable = isTimeSlotAvailable(start, end, existingBookings);
// Find next available slot
import { getNextAvailableSlot } from 'bookingjs';
const nextSlot = getNextAvailableSlot(
afterTime,
duration,
existingBookings,
workingHours
);Member Preferences
// Set member preferences
bookingSystem.setMemberPreferences('member-123', {
preferredGreen: greenId,
preferredBookingType: 'regular',
preferredDuration: 120,
reminderEnabled: true
});
// Get member preferences
const preferences = bookingSystem.getMemberPreferences('member-123');Audit Logging
// Get audit log with filters
const auditLog = bookingSystem.getAuditLog({
start: new Date('2024-01-01'),
end: new Date('2024-01-31'),
memberId: 'member-123',
entityType: 'booking',
action: 'create'
});
// Each audit entry contains:
// - action: 'create', 'update', 'delete', 'cancel'
// - entityType: 'booking', 'green', 'rink', 'bookingType'
// - memberId: who performed the action
// - timestamp: when it happened
// - oldValues/newValues: what changedData Cleanup
// Manual cleanup
const removedBookings = bookingSystem.clearOldBookings(cutoffDate, memberId);
const removedAuditEntries = bookingSystem.purgeAuditLog(cutoffDate, memberId);
// Automatic cleanup based on retention settings
const cleanupSummary = bookingSystem.cleanupSystem(memberId);Persistence
// Serialize to JSON
const jsonData = bookingSystem.toJSON();
// Restore from JSON
const restoredSystem = BookingSystem.fromJSON(jsonData);
// All classes support JSON serialization
const greenJson = green.toJSON();
const restoredGreen = Green.fromJSON(greenJson);Error Handling
BookingJS provides specific error types for different scenarios:
import {
BookingConflictError,
InvalidTimeSlotError,
MemberPermissionError,
ValidationError,
BookingTypeNotAllowedError
} from 'bookingjs';
try {
bookingSystem.createBooking(bookingData, memberId);
} catch (error) {
if (error instanceof BookingConflictError) {
console.log('Booking conflicts with:', error.conflictingBooking);
} else if (error instanceof ValidationError) {
console.log('Validation failed for field:', error.field);
}
// Handle other error types...
}Configuration
Booking Rules
const settings = {
bookingRules: {
maxAdvanceBookingDays: 30, // How far ahead bookings can be made
minAdvanceBookingHours: 2, // Minimum notice required
maxBookingDuration: 180, // Maximum booking length (minutes)
minBookingDuration: 60, // Minimum booking length (minutes)
allowConcurrentBookings: false, // Allow overlapping bookings
requireApproval: false // Require admin approval
}
};Data Retention
const settings = {
dataRetention: {
bookingRetentionDays: 365, // Keep bookings for 1 year
auditLogRetentionDays: 1095, // Keep audit logs for 3 years
autoCleanupEnabled: true, // Enable automatic cleanup
cleanupIntervalDays: 30 // Run cleanup every 30 days
}
};TypeScript Support
BookingJS includes comprehensive TypeScript definitions:
import { BookingSystem, Booking, Green, BookingType } from 'bookingjs';
interface BookingData {
memberId: string;
rinkId: string;
bookingTypeId: string;
date: Date;
start: Date;
end: Date;
notes?: string;
}
const system: BookingSystem = new BookingSystem({ club: 'my-club' });
const booking: Booking = system.createBooking(bookingData, memberId);Testing
Run the test suite:
npm testRun tests with coverage:
npm run test:coverageDevelopment
Building
npm run buildThis generates:
dist/index.js- ES Module builddist/index.cjs- CommonJS builddist/index.d.ts- TypeScript declarations
Development Mode
npm run devRuns Rollup in watch mode for development.
Browser Compatibility
- Modern browsers with ES2020 support
- Node.js 14+
- Supports both ES Modules and CommonJS
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Run the test suite
- Submit a pull request
Support
For issues and questions:
- Repository Issues: Create an issue
- Documentation: See the
/docsfolder for detailed API documentation
Related Projects
- LeagueJS - Sports league management library
Built with ❤️ for the bowling community
