Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Publish to npm

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install dependencies
run: bun install

- name: Run tests
run: bun test

- name: Run type checking
run: bun run typecheck

- name: Run linting
run: bun run lint

- name: Build package
run: bun run build

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'

- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ bun add scheduling-sdk
### Standard Scheduling

```typescript
import { createScheduler } from 'scheduling-sdk'
import { Scheduler } from 'scheduling-sdk'

// Initialize scheduler with busy times (existing meetings, appointments, etc.)
// Busy times are periods when you're NOT available
const scheduler = createScheduler([
const scheduler = new Scheduler([
{
start: new Date('2024-01-15T09:00:00Z'), // Meeting starts at 9:00 AM
end: new Date('2024-01-15T10:00:00Z'), // Meeting ends at 10:00 AM
Expand Down Expand Up @@ -83,9 +83,9 @@ const availableSlots = scheduler.findAvailableSlots(
### Managing Busy Times

```typescript
import { createScheduler } from 'scheduling-sdk'
import { Scheduler } from 'scheduling-sdk'

const scheduler = createScheduler()
const scheduler = new Scheduler()

// Add a single busy time (e.g., a new meeting)
scheduler.addBusyTime({
Expand Down Expand Up @@ -177,9 +177,9 @@ Restrict generated slots to specific local hours by providing a timezone and a d
Core `Scheduler` usage:

```typescript
import { createScheduler } from 'scheduling-sdk'
import { Scheduler } from 'scheduling-sdk'

const scheduler = createScheduler()
const scheduler = new Scheduler()

// Search the whole day in UTC, but only return slots that START between 9:00 and 17:00 New York time
const slots = scheduler.findAvailableSlots(
Expand Down Expand Up @@ -271,8 +271,8 @@ interface SchedulingOptions {
- **📖 [Getting Started](docs/getting-started.md)** - Installation and basic usage
- **📋 [API Reference](docs/api-reference.md)** - Complete API documentation
- **🧠 [Core Concepts](docs/core-concepts.md)** - Understanding scheduling concepts
- **⏰ [Availability API](docs/availability-api.md)** - Weekly availability patterns and scheduling
- **💡 [Examples](docs/examples.md)** - Practical usage examples
- **⏰ [Availability Scheduler](docs/availability-scheduler.md)** - Weekly availability patterns and scheduling
- **💡 [Recipes](docs/recipes.md)** - Practical usage examples
- **⚡ [Performance Guide](docs/performance.md)** - Optimization and benchmarks
- **🤝 [Contributing](docs/contributing.md)** - Development and contribution guidelines

Expand Down
31 changes: 31 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Scheduling SDK Docs

Welcome to the Scheduling SDK documentation. Start here to explore concepts, APIs, and practical recipes.

## Start Here

- [Getting Started](getting-started.md) — installation and a 5‑minute tour
- [Core Concepts](core-concepts.md) — daily windows, K‑overlaps, alignment, and more
- [Availability Scheduler](availability-scheduler.md) — weekly availability patterns and business hours
- [API Reference](api-reference.md) — full signatures and validation rules

## Practical Guides

- [Recipes](recipes.md) — copy‑paste scenarios for common use cases
- [Performance](performance.md) — benchmarks and optimization strategies

## Contributing

- [Contributing Guide](contributing.md)

## When to use what

- Use `Scheduler` when you have busy times and need to find open slots between them.
- Use `AvailabilityScheduler` when you have a recurring weekly availability (e.g., business hours) and also need to apply busy times and daily windows.

## Quick Links (anchors)

- [Daily Windows](core-concepts.md#daily-windows)
- [K-overlaps](core-concepts.md#k-overlaps)
- [Availability Scheduler](availability-scheduler.md)
- [weeklyAvailabilityToBusyTimes](api-reference.md#weeklyavailabilitytobusytimes)
67 changes: 39 additions & 28 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# API Reference

Back: [Availability Scheduler](availability-scheduler.md) • Next: [Recipes](recipes.md)

## Types

### Core Types
Expand Down Expand Up @@ -42,10 +44,19 @@ Configuration options for slot generation.

```typescript
interface SchedulingOptions {
// Required
slotDuration: number

// Optional
slotSplit?: number
padding?: number
offset?: number
maxOverlaps?: number

// Daily window filtering (timezone-aware)
timezone?: string
earliestTime?: string | number // 'HH:mm' or minutes since midnight
latestTime?: string | number // 'HH:mm' or minutes since midnight; supports '24:00' or 1440
}
```

Expand All @@ -55,6 +66,9 @@ interface SchedulingOptions {
- `slotSplit` (optional): Interval between the start times of consecutive slots in minutes. Defaults to `slotDuration`. Must be positive.
- `padding` (optional): Buffer time in minutes to add before and after each busy time. Defaults to 0. Must be non-negative.
- `offset` (optional): Offset from standard time boundaries in minutes. Defaults to 0. Must be non-negative.
- `maxOverlaps` (optional): Allow up to K overlapping busy intervals. If undefined, traditional behavior applies (any overlap blocks a slot).
- `timezone` (optional): IANA timezone identifier used for daily window filtering. Required if `earliestTime`/`latestTime` are provided when using the core `Scheduler`.
- `earliestTime`/`latestTime` (optional): Local daily time window for slot START times. Specify as `HH:mm` or minutes since midnight. `latestTime` accepts `"24:00"` or `1440` as end of day.

### Availability Types

Expand Down Expand Up @@ -91,44 +105,28 @@ Defines a weekly availability pattern with multiple schedules.
```typescript
interface WeeklyAvailability {
schedules: DaySchedule[]
timezone?: string
}
```

**Properties:**

- `schedules`: Array of availability schedules. Must contain at least one schedule.
- `timezone` (optional): IANA timezone identifier (e.g., 'America/New_York', 'Europe/London')

## Functions

### createScheduler

Creates a new Scheduler instance.

```typescript
function createScheduler(busyTimes?: BusyTime[]): Scheduler
```

**Parameters:**

- `busyTimes` (optional): Initial array of busy times. Defaults to empty array.

**Returns:**
### Creating a Scheduler

- New `Scheduler` instance

**Example:**
Instantiate the class directly.

```typescript
import { createScheduler } from 'scheduling-sdk'
import { Scheduler } from 'scheduling-sdk'

// Create empty scheduler
const scheduler = createScheduler()
const scheduler = new Scheduler()

// Create scheduler with initial busy times
const busyScheduler = createScheduler([
{ start: new Date('2024-01-15T10:00:00Z'), end: new Date('2024-01-15T11:00:00Z') },
const busyScheduler = new Scheduler([
{ start: new Date('2024-01-15T10:00:00Z'), end: new Date('2024-01-15T11:00:00Z') },
])
```

Expand Down Expand Up @@ -256,12 +254,13 @@ Enhanced scheduler that combines weekly availability patterns with traditional b
### Constructor

```typescript
constructor(availability?: WeeklyAvailability, existingBusyTimes?: BusyTime[])
constructor(availability?: WeeklyAvailability, timezone?: string, existingBusyTimes?: BusyTime[])
```

**Parameters:**

- `availability` (optional): Weekly availability pattern defining when slots are available
- `timezone` (optional): IANA timezone identifier for availability processing and daily window fallback
- `existingBusyTimes` (optional): Array of existing busy times to include

**Throws:**
Expand All @@ -278,9 +277,14 @@ const scheduler = new AvailabilityScheduler({
schedules: [{ days: ['monday'], start: '09:00', end: '17:00' }],
})

// Create with availability and existing busy times
// Create with availability and timezone
const schedulerTz = new AvailabilityScheduler({
schedules: [{ days: ['monday'], start: '09:00', end: '17:00' }],
}, 'America/New_York')

// Create with availability, timezone, and existing busy times
const busyTimes = [{ start: new Date('2024-01-01T10:00:00Z'), end: new Date('2024-01-01T11:00:00Z') }]
const scheduler = new AvailabilityScheduler(availability, busyTimes)
const schedulerWithAll = new AvailabilityScheduler(availability, 'Europe/London', busyTimes)
```

### setAvailability
Expand All @@ -304,7 +308,6 @@ setAvailability(availability: WeeklyAvailability): void
```typescript
scheduler.setAvailability({
schedules: [{ days: ['monday', 'tuesday'], start: '09:00', end: '17:00' }],
timezone: 'America/New_York',
})
```

Expand Down Expand Up @@ -417,13 +420,18 @@ const slots = scheduler.findAvailableSlots(new Date('2024-01-15T08:00:00Z'), new
Converts a weekly availability pattern into busy times for a specific week.

```typescript
function weeklyAvailabilityToBusyTimes(availability: WeeklyAvailability, weekStart: Date): BusyTime[]
function weeklyAvailabilityToBusyTimes(
availability: WeeklyAvailability,
weekStart: Date,
timezone?: string
): BusyTime[]
```

**Parameters:**

- `availability`: The weekly availability pattern to convert
- `weekStart`: The Monday date for the week to process (MUST be a Monday)
- `timezone` (optional): IANA timezone used to interpret availability times. Falls back to `process.env.SCHEDULING_TIMEZONE` or `UTC`.

**Returns:**

Expand Down Expand Up @@ -483,6 +491,9 @@ All methods perform input validation and will throw descriptive errors for inval
- `slotSplit` must be a positive number (if provided)
- `padding` must be a non-negative number (if provided)
- `offset` must be a non-negative number (if provided)
- `maxOverlaps` must be a non-negative integer (if provided)
- If `earliestTime` or `latestTime` is provided, `timezone` must also be specified when using the core `Scheduler`
- `earliestTime`/`latestTime` must be valid times (string `HH:mm` or minutes). `latestTime` may be `24:00`/`1440`.
- All numeric values must be finite

### Availability Validation
Expand All @@ -493,7 +504,7 @@ All methods perform input validation and will throw descriptive errors for inval
- Time format must be HH:mm (24-hour format)
- Start time must be before end time
- No overlapping schedules on the same day
- Timezone must be valid IANA format (if provided)

## Behavior Details

Expand Down
Loading