A TypeScript library for managing barber shop appointments, built with clean architecture principles and strict type safety.
- π Appointment scheduling and management
- π₯ Customer management
- πββοΈ Service catalog management
- β° Time slot management
- π Booking statistics and reporting
- π Flexible repository pattern
- π― Use case driven architecture
- π Strong type safety with Zod validation
# Using bun
bun add @your-org/appointments
# Using npm
npm install @your-org/appointments
# Using yarn
yarn add @your-org/appointments
import { createAppointmentSystem } from '@your-org/appointments';
// Create an instance of the appointment system
const appointmentSystem = createAppointmentSystem();
// Schedule an appointment
async function scheduleAppointment() {
try {
const appointment = await appointmentSystem.appointments.schedule.execute({
customerId: 'customer-uuid',
serviceId: 'service-uuid',
barberId: 'barber-uuid',
startTime: new Date(),
notes: 'First time customer',
});
console.log('Appointment scheduled:', appointment);
} catch (error) {
console.error('Failed to schedule appointment:', error);
}
}
// Query appointments
async function getUpcomingAppointments() {
const result = await appointmentSystem.appointments.query.execute({
startDate: new Date(),
status: 'confirmed',
page: 1,
pageSize: 10,
sortBy: 'startTime',
sortDirection: 'asc',
});
console.log('Upcoming appointments:', result);
}
The library follows Clean Architecture principles with the following layers:
- Core business entities and logic
- Repository interfaces
- Domain events and types
- Use cases implementing business operations
- Input validation and error handling
- Business rules enforcement
- Repository implementations
- External service integrations
- Data persistence
const appointment = await appointmentSystem.appointments.schedule.execute({
customerId: string;
serviceId: string;
barberId: string;
startTime: Date;
notes?: string;
});
await appointmentSystem.appointments.cancel.execute({
appointmentId: string;
cancellationReason: string;
cancelledBy: string;
});
await appointmentSystem.appointments.reschedule.execute({
appointmentId: string;
newStartTime: Date;
barberId: string;
rescheduledBy: string;
reason?: string;
});
await appointmentSystem.appointments.complete.execute({
appointmentId: string;
completedBy: string;
notes?: string;
feedback?: {
rating?: number;
comment?: string;
serviceQuality?: number;
timeliness?: number;
cleanliness?: number;
};
paymentStatus: 'PAID' | 'PENDING' | 'FAILED';
paymentMethod?: 'CASH' | 'CARD' | 'DIGITAL_WALLET';
});
The library provides built-in in-memory repositories and interfaces for implementing custom storage solutions:
interface IRepository<T> {
findById(id: string): Promise<T | null>;
findAll(): Promise<T[]>;
create(entity: T): Promise<T>;
update(id: string, entity: T): Promise<T>;
delete(id: string): Promise<void>;
}
interface IAdvancedRepository<T> extends IRepository<T> {
findWithFilters(filters: IFilterOptions, options?: IQueryOptions): Promise<IPagedResult<T>>;
exists(filter: IFilterOptions): Promise<boolean>;
count(filter?: IFilterOptions): Promise<number>;
findOne(filter: IFilterOptions): Promise<T | null>;
}
The library uses custom error classes for different scenarios:
try {
await appointmentSystem.appointments.schedule.execute(/* ... */);
} catch (error) {
if (error instanceof ScheduleAppointmentError) {
// Handle scheduling specific error
console.error(`Scheduling failed: ${error.message} (${error.code})`);
} else {
// Handle other errors
console.error('Unexpected error:', error);
}
}
# Install dependencies
bun install
# Run tests
bun test
# Build the library
bun run build
# Type check
bun run lint
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License with the Commons Clause.
- You may freely use, modify, and distribute this software for non-commercial purposes.
- If you wish to use this software in a commercial product or service, you must obtain a commercial license from [Your Name or Company].
For more details, see the LICENSE
file.
For support, please open an issue in the GitHub repository or contact the maintainers.