🏗️ Modular Architecture: Clean separation of concerns for maintainability and testing
🧪 98%+ Test Coverage: Comprehensive testing with edge case handling (Supported by the CODE's Automated Testing LU)
Note
The SDK is fully written in TypeScript and uses Bun as the build and test tool. It requires TypeScript 5.0 or later as a peer dependency. While we use Bun for development, the compiled SDK is compatible with any JavaScript runtime, including Node.js, Deno, and modern browsers with ESM support.
# Install the SDK
npm install scheduling-sdk
# or
bun add scheduling-sdk
Zero configuration required - start scheduling in seconds! 🚀
Busy Times: Periods when you're NOT available (meetings, appointments, breaks)
Available Slots: Free time periods where new events can be scheduled
Time Range: The window (start/end dates) to search for available slots
Slot Options: Configuration for how slots are generated (duration, padding, etc.)
import{Scheduler}from'scheduling-sdk'// Initialize scheduler with busy times (existing meetings, appointments, etc.)// Busy times are periods when you're NOT availableconstscheduler=newScheduler([{start: newDate('2024-01-15T09:00:00Z'),// Meeting starts at 9:00 AMend: newDate('2024-01-15T10:00:00Z'),// Meeting ends at 10:00 AM},])// Find available time slots in a given time range// This will return all free slots between 8:00 AM and 5:00 PM, excluding the busy timeconstavailableSlots=scheduler.findAvailableSlots(newDate('2024-01-15T08:00:00Z'),// Search from 8:00 AMnewDate('2024-01-15T17:00:00Z'),// Search until 5:00 PM{slotDuration: 30,// Each available slot will be 30 minutes longpadding: 15,// Add 15-minute buffer before and after busy timesslotSplit: 15,// Generate overlapping slots every 15 minutesoffset: 0,// No offset from hour boundaries})// Result: availableSlots will contain time slots like:// [// { start: "2024-01-15T08:00:00Z", end: "2024-01-15T08:30:00Z" },// { start: "2024-01-15T08:15:00Z", end: "2024-01-15T08:45:00Z" },// { start: "2024-01-15T10:15:00Z", end: "2024-01-15T10:45:00Z" }, // Note: starts at 10:15 due to 15-min padding// { start: "2024-01-15T10:30:00Z", end: "2024-01-15T11:00:00Z" },// ...// ]
import{Scheduler}from'scheduling-sdk'constscheduler=newScheduler()// Add a single busy time (e.g., a new meeting)scheduler.addBusyTime({start: newDate('2024-01-15T14:00:00Z'),// 2:00 PMend: newDate('2024-01-15T15:00:00Z'),// 3:00 PM})// Add multiple busy times at once (e.g., imported from calendar)scheduler.addBusyTimes([{start: newDate('2024-01-15T10:00:00Z'),// Morning standupend: newDate('2024-01-15T11:00:00Z'),},{start: newDate('2024-01-15T16:00:00Z'),// Client callend: newDate('2024-01-15T17:00:00Z'),},])// Clear all busy times (e.g., starting fresh)scheduler.clearBusyTimes()// Get current busy times (returns a sorted array)constcurrentBusyTimes=scheduler.getBusyTimes()// Returns: [// { start: "2024-01-15T10:00:00Z", end: "2024-01-15T11:00:00Z" },// { start: "2024-01-15T14:00:00Z", end: "2024-01-15T15:00:00Z" },// ...// ]
Weekly Availability Scheduling
Business hours made easy ;)
import{AvailabilityScheduler}from'scheduling-sdk'// Define when you're generally available (business hours)// This creates recurring weekly patternsconstavailability={schedules: [// Monday-Friday: 9 AM to 12 PM (morning hours){days: ['monday','tuesday','wednesday','thursday','friday'],start: '09:00',end: '12:00'},// Monday-Friday: 1 PM to 5 PM (afternoon hours, after lunch){days: ['monday','tuesday','wednesday','thursday','friday'],start: '13:00',end: '17:00'},// Saturday: 10 AM to 2 PM{days: ['saturday'],start: '10:00',end: '14:00'},],}constscheduler=newAvailabilityScheduler(availability)// Add busy times within your available hours (meetings, appointments, etc.)scheduler.addBusyTimes([{start: newDate('2024-01-15T14:00:00Z'),// Monday 2 PM meetingend: newDate('2024-01-15T15:00:00Z'),},{start: newDate('2024-01-16T10:00:00Z'),// Tuesday 10 AM appointmentend: newDate('2024-01-16T11:00:00Z'),},])// Find available slots only within your defined business hours// This respects both your availability schedule AND busy timesconstslots=scheduler.findAvailableSlots(newDate('2024-01-15T08:00:00Z'),// Monday 8 AMnewDate('2024-01-15T18:00:00Z'),// Monday 6 PM{slotDuration: 60,// 1-hour slots})// Result: Only returns slots during business hours (9-12, 1-5) excluding busy times// [// { start: "2024-01-15T09:00:00Z", end: "2024-01-15T10:00:00Z" },// { start: "2024-01-15T13:00:00Z", end: "2024-01-15T14:00:00Z" },// { start: "2024-01-15T15:00:00Z", end: "2024-01-15T16:00:00Z" },// { start: "2024-01-15T16:00:00Z", end: "2024-01-15T17:00:00Z" },// ...// ]
Daily Time Windows and Timezone Filtering
Restrict generated slots to specific local hours by providing a timezone and a daily window.
Core Scheduler usage:
import{Scheduler}from'scheduling-sdk'constscheduler=newScheduler()// Search the whole day in UTC, but only return slots that START between 9:00 and 17:00 New York timeconstslots=scheduler.findAvailableSlots(newDate('2024-01-15T00:00:00Z'),newDate('2024-01-15T23:59:59Z'),{slotDuration: 60,timezone: 'America/New_York',earliestTime: '09:00',latestTime: '17:00',})// In January, America/New_York is UTC-5, so this filters to 14:00–22:00 UTC
Availability AvailabilityScheduler usage (timezone can be omitted in options; it falls back to the scheduler’s timezone):
import{AvailabilityScheduler}from'scheduling-sdk'constavailability={schedules: [{days: ['monday','tuesday','wednesday','thursday','friday'],start: '09:00',end: '17:00'}],}constscheduler=newAvailabilityScheduler(availability,'America/New_York')constslots=scheduler.findAvailableSlots(newDate('2024-01-15T00:00:00Z'),newDate('2024-01-15T23:59:59Z'),{slotDuration: 30,// No timezone here → uses scheduler's timezone automaticallyearliestTime: 9*60,// numbers = minutes since midnightlatestTime: '24:00',// string format supports '24:00' for end of day})
Daily window parameters:
timezone (string, IANA ID, e.g. "America/New_York") — required when using earliestTime/latestTime with the core Scheduler.
earliestTime (string HH:mm or number minutes) — lowest local start time to allow.
latestTime (string HH:mm or number minutes) — highest local start time to allow; supports "24:00" or 1440.
Notes:
If you use AvailabilityScheduler, you may omit timezone in findAvailableSlots when using earliestTime/latestTime; it will default to the scheduler’s timezone.
If you use the core Scheduler, providing earliestTime/latestTime without timezone will throw a validation error.
Daily windows filter by slot START time.
Allowing Overlaps (K-overlaps)
You can allow up to K overlapping busy intervals by setting maxOverlaps in options. This uses an optimized algorithm internally.
🤝 Contributing - Development and contribution guidelines
# Install dependencies
bun install
# Run in development mode
bun run dev
# Build for production
bun run build
# Run tests
bun test# Type checking
bun run typecheck
The SDK is built with a modular architecture:
src/
├── types/ # TypeScript type definitions
├── helpers/ # Utility functions organized by domain
│ ├── time/ # Date/time calculations and alignments
│ ├── busy-time/ # Busy time operations (padding, merging, overlap)
│ ├── slot/ # Slot generation and filtering
│ └── availability/ # Weekly availability conversion
├── validators/ # Input validation functions
├── core/ # Main Scheduler class
├── availability/ # AvailabilityScheduler class
└── utils/ # Shared constants and utilities