Skip to main content

Overview

KnowledgeCheckr uses Zod for runtime type validation and TypeScript type inference. All schemas are defined in /src/schemas/ and provide robust validation for API requests and database operations.

KnowledgeCheck Schema

The main schema for creating and managing knowledge checks. Source: src/schemas/KnowledgeCheck.ts

TypeScript Type

type KnowledgeCheck = {
  id: string                          // UUID
  name: string                        // Knowledge check name
  description: string | null          // Optional description
  difficulty?: number                 // 1-10 scale
  questions: Question[]               // Array of questions
  questionCategories?: CategorySchema[] // Question categories
  share_key: string | null           // Share token
  openDate: Date                     // When check becomes available
  closeDate: Date | null             // Optional end date
  createdAt?: Date
  updatedAt?: Date
  owner_id: string                   // User ID (max 36 chars)
  collaborators: string[]            // Array of user IDs
  settings: KnowledgeCheckSettings   // Check settings
}

Field Specifications

id
string
default:"auto-generated UUID"
Unique identifier for the knowledge check. Automatically generated if not provided.
name
string
default:"'Knowledge Check'"
The name under which the created check is associated with.
description
string | null
default:"auto-generated lorem"
Describe the concept of your knowledge check using a few words.
difficulty
number
default:"random 1-10"
Defines the skill level needed for this check. Must be between 1 and 10.
questions
Question[]
required
Array of questions. All question IDs must be unique.
questionCategories
CategorySchema[]
default:"[{id: UUID, name: 'general', ...}]"
Categories for organizing questions. Questions must reference existing categories.
openDate
Date | string
default:"new Date()"
The day on which users can start to use the check.
closeDate
Date | string | null
default:"null"
The last day on which the check can be used by others. Cannot be before openDate.
owner_id
string
required
User ID of the check owner. Maximum 36 characters.
collaborators
string[]
default:"[]"
Array of user IDs who can collaborate on this check.
settings
KnowledgeCheckSettings
required
Configuration settings for practice and examination modes.

Validation Rules

  • Question IDs must be unique
  • All questions must reference a defined category
  • closeDate cannot be before openDate
  • owner_id must be a valid user ID (max 36 characters)

Usage Example

import { safeParseKnowledgeCheck, instantiateKnowledgeCheck } from '@/schemas/KnowledgeCheck'

// Validate existing data
const { success, error, data } = safeParseKnowledgeCheck(checkData)

if (!success) {
  console.error('Validation failed:', error)
} else {
  // data is fully typed and validated
  console.log(data.name)
}

// Create new instance with defaults
const newCheck = instantiateKnowledgeCheck({
  owner_id: 'user-123',
  questions: [/* ... */],
  settings: {/* ... */}
})

Question Schema

Schemas for different question types. Source: src/schemas/QuestionSchema.ts

Base Question

All question types share these base fields:
id
string
required
UUID identifier for the question.
points
number
required
Points awarded for correct answer. Must be positive.
category
string
default:"'general'"
Category name this question belongs to.
question
string
required
The question text. Must be at least 3 words long.
accessibility
'all' | 'practice-only' | 'exam-only'
default:"'all'"
Specifies in which environments the question should be displayed.

Question Types

Single Choice

Questions with exactly one correct answer.
type SingleChoice = {
  type: 'single-choice'
  answers: Array<{
    id: string        // UUID
    answer: string    // Answer text
    correct: boolean  // Exactly one must be true
  }>
} & BaseQuestion
Validation:
  • Must have at least one answer
  • Exactly one answer must be marked as correct
  • All answer IDs and text must be unique
Example:
import { instantiateSingleChoice } from '@/schemas/QuestionSchema'

const question = instantiateSingleChoice({
  id: '123e4567-e89b-12d3-a456-426614174000',
  points: 10,
  question: 'What is the capital of France?',
  type: 'single-choice',
  answers: [
    { id: 'ans-1', answer: 'London', correct: false },
    { id: 'ans-2', answer: 'Paris', correct: true },
    { id: 'ans-3', answer: 'Berlin', correct: false }
  ]
})

Multiple Choice

Questions with one or more correct answers.
type MultipleChoice = {
  type: 'multiple-choice'
  answers: Array<{
    id: string        // UUID
    answer: string    // Answer text
    correct: boolean  // At least one must be true
  }>
} & BaseQuestion
Validation:
  • Must have at least one answer
  • At least one answer must be marked as correct
  • All answer IDs and text must be unique

Drag and Drop

Questions where users order items in a specific sequence.
type DragDropQuestion = {
  type: 'drag-drop'
  answers: Array<{
    id: string       // UUID
    answer: string   // Answer text
    position: number // 0-based position in sequence
  }>
} & BaseQuestion
Validation:
  • Positions must start from 0
  • Positions must form a continuous range [0, n-1]
  • No duplicate positions allowed
  • All answer IDs and text must be unique
Example:
const dragDropQuestion = {
  id: '123e4567-e89b-12d3-a456-426614174001',
  type: 'drag-drop',
  points: 15,
  question: 'Order these events chronologically',
  answers: [
    { id: 'ans-1', answer: 'World War I', position: 0 },
    { id: 'ans-2', answer: 'World War II', position: 1 },
    { id: 'ans-3', answer: 'Cold War', position: 2 }
  ]
}

Open Question

Free-form text questions.
type OpenQuestion = {
  type: 'open-question'
  expectation?: string  // Optional expected answer
} & BaseQuestion

Category Schema

Organize questions into categories with prerequisite support. Source: src/schemas/CategorySchema.ts
type CategorySchema = {
  id: string                        // UUID (auto-generated)
  name: string                      // Category name
  prequisiteCategoryId: string | null  // Optional prerequisite
  skipOnMissingPrequisite: boolean     // Skip if prerequisite not met
}
id
string
default:"auto-generated UUID"
Unique identifier for the category.
name
string
required
Name of the category.
prequisiteCategoryId
string | null
default:"null"
ID of a prerequisite category. Must not be empty string if set.
skipOnMissingPrequisite
boolean
default:"false"
Whether to skip questions in this category if prerequisite is not met.

KnowledgeCheck Settings Schema

Configuration for practice and examination modes. Source: src/schemas/KnowledgeCheckSettingsSchema.ts
type KnowledgeCheckSettings = {
  id: string
  practice: {
    enablePracticing: boolean         // Enable practice mode
    allowedPracticeCount: number | null  // null = unlimited
  }
  examination: {
    enableExaminations: boolean       // Enable exam mode
    startDate: Date                   // When exams can start
    endDate: Date | null             // When exams end (null = no limit)
    questionOrder: 'create-order' | 'random'
    answerOrder: 'create-order' | 'random'
    allowAnonymous: boolean          // Allow anonymous users
    allowFreeNavigation: boolean     // Allow question navigation
    examTimeFrameSeconds: number     // 60-18001 seconds (1min-5hrs)
    examinationAttemptCount: number  // Min 1 attempt
  }
  shareAccessibility: boolean        // Publicly discoverable
}

Practice Settings

practice.enablePracticing
boolean
default:"true"
Defines whether users are able to practice with this check or not.
practice.allowedPracticeCount
number | null
default:"null"
The amount of practice attempts users have. When set to null, users have unlimited attempts. Minimum 1 if set.

Examination Settings

examination.enableExaminations
boolean
default:"true"
Defines whether users are able to start an examination attempt for this check.
examination.startDate
Date | string
default:"new Date()"
The start-date on which users can start examinations.
examination.endDate
Date | string | null
default:"1 year from now"
The end-date after which users can no longer start examinations. Set to null for no end constraint.
examination.questionOrder
'create-order' | 'random'
default:"'random'"
Defines how questions are ordered during exams.
examination.answerOrder
'create-order' | 'random'
default:"'random'"
Defines how answers are ordered during exams.
examination.allowAnonymous
boolean
default:"true"
Specifies whether anonymous users can interact with this check.
examination.allowFreeNavigation
boolean
default:"true"
Specifies whether users can switch between questions freely.
examination.examTimeFrameSeconds
number
default:"3600"
The max duration users have to finish their examination attempt. Must be between 60 and 18001 seconds (1 minute to 5 hours).
examination.examinationAttemptCount
number
default:"1"
The amount of examination attempts users have. Minimum 1.

Examination Schema

Tracks examination attempts and results. Source: src/schemas/ExaminationSchema.ts
type ExaminationSchema = {
  knowledgeCheck: KnowledgeCheck  // The check being examined
  startedAt: Date                 // When exam started
  finishedAt: Date | null        // When exam completed
  score: number                  // Current score
  results: QuestionInput[]       // User's answers
}
knowledgeCheck
KnowledgeCheck
required
The knowledge check being examined (with schema effects stripped).
startedAt
Date
default:"new Date()"
Timestamp when the examination started.
finishedAt
Date | null
default:"null"
Timestamp when the examination was completed. Null if still in progress.
score
number
default:"0"
Current score for the examination.
results
QuestionInput[]
default:"[]"
Array of user’s answers to questions.

Custom Zod Types

Source: src/schemas/CustomZodTypes.ts

StringDate

Accepts either a Date object or ISO date string and transforms it to a Date.
const StringDate = z
  .union([z.date(), z.string()])
  .transform((date) => (typeof date === 'string' ? new Date(date) : date))
  .refine((check) => !isNaN(check.getTime()), 'Invalid date value provided')
Usage:
// Both are valid
StringDate.parse(new Date())
StringDate.parse('2024-03-01T12:00:00Z')

Schema Utilities

All schemas export three utility functions:
// Validate and throw on error
const data = validateKnowledgeCheck(input)

// Safe parsing with error handling
const { success, error, data } = safeParseKnowledgeCheck(input)

// Create instance with defaults
const instance = instantiateKnowledgeCheck(partialInput)
Source: src/schemas/utils/schemaUtilities.ts

Build docs developers (and LLMs) love