BlackoutService
Create and manage blackout windows with impact analysis
Overview
BlackoutService manages blackout windows that block bookings for rooms, floors, buildings, campuses, or entire institutions. It supports impact analysis to identify existing bookings affected by a new blackout and cascades blackouts up the location hierarchy.
import { BlackoutService } from '@roomkit/nestjs';Methods
create
Create a new blackout window. Validates that startsAt is before endsAt and emits a BlackoutCreated domain event.
async create(data: Omit<BlackoutWindow, 'id' | 'createdAt'>): Promise<BlackoutWindow>| Parameter | Type | Description |
|---|---|---|
data | Omit<BlackoutWindow, 'id' | 'createdAt'> | Blackout window data |
BlackoutWindow fields:
| Field | Type | Description |
|---|---|---|
locationNodeId | string | The location node this blackout applies to |
scope | 'room' | 'floor' | 'building' | 'campus' | 'institution' | Scope of the blackout |
title | string | Display title for the blackout |
reason | string | null | Optional reason for the blackout |
startsAt | Date | Start of the blackout window |
endsAt | Date | End of the blackout window |
isRecurring | boolean | Whether the blackout recurs |
recurrenceRuleId | string | null | Optional recurrence rule ID |
const blackout = await blackoutService.create({
locationNodeId: 'building-science',
scope: 'building',
title: 'Annual Maintenance',
reason: 'HVAC system replacement',
startsAt: new Date('2026-07-01T00:00:00'),
endsAt: new Date('2026-07-14T23:59:59'),
isRecurring: false,
recurrenceRuleId: null,
});Throws InvalidTimeRangeError if startsAt is not before endsAt.
getActiveBlackouts
Get all active blackout windows for a location node within a time range. Cascades up the location hierarchy, so a blackout on a building also applies to all rooms within it.
async getActiveBlackouts(locationNodeId: string, timeRange: { start: Date; end: Date }): Promise<BlackoutWindow[]>| Parameter | Type | Description |
|---|---|---|
locationNodeId | string | The location node to check |
timeRange | { start: Date; end: Date } | Time range to check for active blackouts |
const blackouts = await blackoutService.getActiveBlackouts('room-a1', {
start: new Date('2026-07-01'),
end: new Date('2026-07-31'),
});
// Returns blackouts on the room itself AND any ancestor nodes (floor, building, etc.)analyzeImpact
Analyze the impact of a blackout window by resolving all descendant rooms and checking each for overlapping bookings. Emits a BlackoutImpactDetected domain event if any affected bookings are found.
async analyzeImpact(blackout: BlackoutWindow): Promise<Booking[]>| Parameter | Type | Description |
|---|---|---|
blackout | BlackoutWindow | The blackout window to analyze |
Returns an array of bookings that overlap with the blackout window.
const affectedBookings = await blackoutService.analyzeImpact(blackout);
if (affectedBookings.length > 0) {
console.log(`${affectedBookings.length} bookings affected by blackout`);
for (const booking of affectedBookings) {
console.log(`- Booking ${booking.id} in room ${booking.roomId}`);
}
}delete
Delete a blackout window.
async delete(id: string): Promise<void>| Parameter | Type | Description |
|---|---|---|
id | string | The blackout window ID |
await blackoutService.delete('blackout-1');