npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bookingjs

v0.1.6

Published

A framework-agnostic JavaScript library for managing rink bookings, availability, and scheduling

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 bookingjs

Quick 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 above

Core 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 minutes

BookingType

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

Advanced 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 changed

Data 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 test

Run tests with coverage:

npm run test:coverage

Development

Building

npm run build

This generates:

  • dist/index.js - ES Module build
  • dist/index.cjs - CommonJS build
  • dist/index.d.ts - TypeScript declarations

Development Mode

npm run dev

Runs 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

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Run the test suite
  6. Submit a pull request

Support

For issues and questions:

  • Repository Issues: Create an issue
  • Documentation: See the /docs folder for detailed API documentation

Related Projects

  • LeagueJS - Sports league management library

Built with ❤️ for the bowling community