CourseKitBackend
Prisma Adapter
Out-of-the-box Prisma storage adapters for all CourseKit entities
Overview
CourseKit ships with Prisma adapters for every storage interface. The adapters map between Prisma's generated types and CourseKit's structural types without importing @prisma/client in the core package.
Available Adapters
| Adapter | Storage Interface | Prisma Models Used |
|---|---|---|
PrismaTimetableEventAdapter | TimetableEventStorage | timetableEvent, eventException, eventInstructor, eventGroup |
PrismaRoomAdapter | RoomStorage | room |
PrismaInstructorAdapter | InstructorStorage | instructor |
PrismaGroupAdapter | GroupStorage | group, studentGroup |
PrismaAvailabilityAdapter | AvailabilityStorage | availability |
PrismaAcademicPeriodAdapter | AcademicPeriodStorage | academicPeriod |
PrismaCourseAdapter | CourseStorage | course |
PrismaLocationDistanceAdapter | LocationDistanceStorage | locationDistance |
Instantiation
Each adapter takes Prisma delegate(s) as constructor arguments:
import { PrismaClient } from '@prisma/client';
import {
PrismaTimetableEventAdapter,
PrismaRoomAdapter,
PrismaInstructorAdapter,
PrismaGroupAdapter,
PrismaAvailabilityAdapter,
PrismaAcademicPeriodAdapter,
PrismaCourseAdapter,
PrismaLocationDistanceAdapter,
} from '@hfu.digital/coursekit-nestjs';
const prisma = new PrismaClient();
// TimetableEventAdapter needs 4 delegates
const eventStorage = new PrismaTimetableEventAdapter(
prisma.timetableEvent,
prisma.eventException,
prisma.eventInstructor,
prisma.eventGroup,
);
// GroupAdapter needs 2 delegates
const groupStorage = new PrismaGroupAdapter(prisma.group, prisma.studentGroup);
// All others need 1 delegate
const roomStorage = new PrismaRoomAdapter(prisma.room);
const instructorStorage = new PrismaInstructorAdapter(prisma.instructor);
const availabilityStorage = new PrismaAvailabilityAdapter(prisma.availability);
const periodStorage = new PrismaAcademicPeriodAdapter(prisma.academicPeriod);
const courseStorage = new PrismaCourseAdapter(prisma.course);
const locationStorage = new PrismaLocationDistanceAdapter(prisma.locationDistance);Prisma Schema
See the Getting Started page for the full Prisma schema definition.
Structural Typing
CourseKit uses structural typing (duck typing) instead of importing @prisma/client:
// CourseKit defines this interface
interface TimetableEvent {
id: string;
title: string;
startTime: Date;
durationMin: number;
// ...
}
// Prisma generates a compatible type
// The adapter maps between them without couplingThis means:
- The core package has zero ORM dependencies
- Adapters can be swapped without changing domain logic
- Custom adapters for other ORMs only need to match the interface shape
Optimistic Concurrency
The PrismaTimetableEventAdapter supports optimistic concurrency via the version field. Pass expectedVersion to update() to ensure the event hasn't been modified since you last read it:
await eventStorage.update('event-1', { title: 'Updated' }, 3);
// Throws if current version !== 3