
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling
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.
npm install bookingjs
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);
const { BookingSystem, Green, Rink } = require('bookingjs');
// Same usage as above
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();
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);
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);
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 minutes
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 types
// 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
);
// Set member preferences
bookingSystem.setMemberPreferences('member-123', {
preferredGreen: greenId,
preferredBookingType: 'regular',
preferredDuration: 120,
reminderEnabled: true
});
// Get member preferences
const preferences = bookingSystem.getMemberPreferences('member-123');
// 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 changed
// 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);
// 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);
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...
}
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
}
};
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
}
};
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);
Run the test suite:
npm test
Run tests with coverage:
npm run test:coverage
npm run build
This generates:
dist/index.js - ES Module builddist/index.cjs - CommonJS builddist/index.d.ts - TypeScript declarationsnpm run dev
Runs Rollup in watch mode for development.
MIT License - see LICENSE file for details.
For issues and questions:
/docs folder for detailed API documentationBuilt with ❤️ for the bowling community
FAQs
A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling
The npm package bookingjs receives a total of 0 weekly downloads. As such, bookingjs popularity was classified as not popular.
We found that bookingjs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.