npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@telebort/question-banks

v2.1.1

Published

Question Banks SDK with three-tier access: Free (schemas), Standard (validation), Premium (full access + grading)

Readme

@telebort/question-banks

Question Banks SDK for Telebort educational assessments. Provides Zod schemas, TypeScript types, client-side quiz generation, v2.0 Knowledge Graph access, and CAT (Computerized Adaptive Testing) orchestration.

v2.1.0 - Full CAT engine with Sympson-Hetter exposure control, IRT 4PL calibration, and 256K question bank access.

Installation

npm install @telebort/question-banks zod

What's New in v2.1.0

CAT Orchestration Engine

  • Sympson-Hetter Exposure Control: Industry-standard algorithm (used in GRE, GMAT) to prevent item overexposure
  • Stopping Rules: SE-threshold + fixed-length dual criteria for test termination
  • Content Balancing: Blueprint constraint satisfaction for topic coverage
  • IRT 4PL: Full 4-parameter logistic model with estimateAbilityEAP() Bayesian estimation

Scale

  • 256K Questions: 26 CDN shards (~20MB each) for global delivery
  • Malaysian Math: 94K bilingual questions (KSSR 30K + KSSM 22K + SPM 34K + STPM 8K)
  • Knowledge Graph v2.0: 4-level taxonomy with topic-based queries

Previous Additions (v1.4.x)

  • Malaysian Math Module: sdk.malaysiaMath for procedural question generation
  • 104 Templates: KSSR, KSSM, SPM Add Maths, STPM covering Years 1-6, Forms 1-6
  • Bilingual: Bahasa Malaysia and English support

Architecture

The SDK provides client-side access to question bank data via CDN:

┌─────────────────────────────────────────────────────────────┐
│                    SDK Access Patterns                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  v1.x Compatibility (Course-based)                          │
│  └── sdk.data.getCourse('CS1')                              │
│                                                              │
│  v2.0 Knowledge Graph (Topic-based)                         │
│  ├── sdk.knowledge.getByTopic('algorithms/sorting')         │
│  └── sdk.taxonomy.getDomains()                              │
│                                                              │
│  Premium API (JWT-authenticated)                             │
│  └── PremiumClient with offline fallback                    │
│                                                              │
└─────────────────────────────────────────────────────────────┘

No server required - all operations work client-side.


Quick Start (CDN Mode)

Fetch questions from CDN for automatic updates:

import { createQuestionBanksSDK } from '@telebort/question-banks'

const CDN_BASE = 'https://content-warehouse.vercel.app/question-banks/v1.1/courses'

const sdk = createQuestionBanksSDK({
  dataSource: {
    async loadCourses() {
      const codes = ['AI1', 'M1', 'W1', 'CS1']
      const courses = await Promise.all(
        codes.map(code => fetch(`${CDN_BASE}/${code}.json`).then(r => r.json()))
      )
      return courses
    }
  }
})

// Generate a quiz
const quiz = await sdk.quiz.generateQuiz({ questionCount: 5 })

// Check an answer with feedback
const result = await sdk.validate.checkAnswer('ai-1-l1-q1', 'B', 'formative')
// { isCorrect: true, feedback: {...}, misconceptionId: null }

v2.0 Knowledge Graph

Access questions by topic instead of course. Query across curricula with the 4-level taxonomy.

Full Guide: See KNOWLEDGE-GRAPH.md for complete API reference and examples.

Taxonomy Structure

Domain (L1)          Strand (L2)          Topic (L3)
    │                    │                    │
computer-science ──→ algorithms ──────→ sorting
                     data-structures ──→ arrays, trees, graphs

web-development ──→ javascript ───────→ arrow-functions, promises
                     html-css ─────────→ flexbox, grid

6 Domains: computer-science, artificial-intelligence, web-development, mathematics, computational-thinking, mobile-development

Basic Usage

import { createKnowledgeModule, createTaxonomyModule } from '@telebort/question-banks'

const CDN_BASE = 'https://content-warehouse.vercel.app'

// Create modules
const knowledge = createKnowledgeModule({ cdnBase: CDN_BASE })
const taxonomy = createTaxonomyModule({ cdnBase: CDN_BASE })

// Get questions by topic path
const sorting = await knowledge.getByTopic('computer-science/algorithms/sorting')
console.log(`${sorting.length} sorting questions`)  // Returns TopicQuestionRef[]

// Browse taxonomy
const domains = await taxonomy.getDomains()
const strands = await taxonomy.getStrands('computer-science')

Advanced Search with Filters

// Find medium-difficulty sorting questions from CS1
const results = await knowledge.search({
  domain: 'computer-science',
  strand: 'algorithms',
  topic: 'sorting',
  difficulty: 'medium',
  courseCode: 'CS1',
  limit: 10,
  offset: 0
})

// Paginate through all web-dev questions
let page = await knowledge.search({ domain: 'web-development', limit: 50, offset: 0 })

Error Handling with Debug Logging

const knowledge = createKnowledgeModule({
  cdnBase: CDN_BASE,
  cacheEnabled: true,           // Enable caching
  debug: true,                  // Log to console
  onError: (error, context) => {
    console.error(`[${context}]`, error.message)
    // Send to monitoring: Sentry.captureException(error)
  }
})

v2.0 CDN Structure (256K Questions)

/question-banks/v2.0/
├── courses/{CODE}.json                      # Course-based (v1.x compatible)
├── by-topic/{domain}/{strand}/{topic}.json  # Topic-based indexes
├── taxonomy/topics.json                     # 4-level topic tree
└── master/
    ├── knowledge-bank-index.json            # Shard metadata (50KB)
    └── shards/shard-{00001-00026}.json      # 10K questions each (~20MB)

Total: 256,037 questions in 26 CDN shards for global delivery.


CDN Endpoints

Base URL: https://content-warehouse.vercel.app

| Endpoint | Size | Content | |----------|------|---------| | /question-banks/v1.1/courses/AI1.json | ~400KB | Single course | | /question-banks/v1.1/courses/M1.json | ~400KB | Single course | | /certification/v1.1/courses/AI1.json | ~2KB | Certification metadata |

Available Courses: AI1, AI2, AI25, AI3, M1, M2, M3, W1, W2, W3, W35, W4, F1, F2, JC, BBW, BBP, BBD, BBAI, CS1, CS2, CS3, CS4


Static Mode (Bundled JSON)

For offline-first apps, bundle the JSON with your build:

import { createQuestionBanksSDK } from '@telebort/question-banks'
import coursesData from './data/courses.json'

const sdk = createQuestionBanksSDK({
  dataSource: {
    async loadCourses() {
      return coursesData.courses
    }
  }
})

// All SDK features work offline
const courses = await sdk.data.getCourses()
const quiz = await sdk.quiz.generateQuiz({ questionCount: 5 })
const result = await sdk.validate.checkAnswer('ai-1-l1-q1', 'B', 'formative')

Premium Client (JWT-Authenticated)

For full API access with offline fallback (v1.3.0+):

import { PremiumClient } from '@telebort/question-banks/premium'

const client = new PremiumClient({
  token: 'your-jwt-token',

  // Offline support (v1.3.0)
  offlineFallback: true,   // Use cache when network fails
  cacheTTL: 300000,        // 5 minutes cache TTL

  // Rate limiting (built-in: 10 req/s, burst 20)
  timeout: 30000,          // Request timeout

  // Debug logging
  logger: (msg, level) => console.log(`[${level}] ${msg}`),
})

// Preload courses for offline use
await client.preloadForOffline(['cs-1', 'cs-2', 'ai-1'])

// Fetch questions (uses cache if offline)
const { questions, total, hasMore } = await client.getQuestions({
  courseId: 'cs-1',
  difficulty: 'medium',
  limit: 10,
})

// Grade an assessment
const result = await client.gradeAssessment({
  assessmentId: 'uuid-here',
  courseId: 'cs-1',
  submittedAt: new Date().toISOString(),
  responses: [
    { questionId: 'q1', selectedAnswer: 'A' },
    { questionId: 'q2', selectedAnswer: 'B' },
  ]
})

// Cache management
const stats = client.getCacheStats()
console.log(`Cached entries: ${stats.entries}`)
client.clearCache()

SDK Interface

interface QuestionBanksSDK {
  // v1.x Course-based access
  data: {
    getCourses(): Promise<Course[]>
    getCourse(courseId: string): Promise<Course | null>
    getLesson(courseId: string, lessonNumber: number): Promise<Lesson | null>
    getQuestion(questionId: string): Promise<Question | null>
    getAllQuestions(): Promise<Question[]>
  }

  query: {
    filterQuestions(filters: QuestionFilters): Promise<QueryResult<Question>>
    getRandomQuestions(count: number, filters?: QuestionFilters): Promise<Question[]>
  }

  quiz: {
    generateQuiz(criteria: QuizCriteria): Promise<{ questions: Question[]; metadata: object }>
    getLessonQuiz(courseId: string, lessonNumber: number): Promise<Question[]>
  }

  search: {
    search(options: SearchOptions): Promise<QueryResult<Question>>
    searchByTags(tags: string[], matchAll?: boolean): Promise<Question[]>
  }

  analytics: {
    getStatistics(): Promise<Statistics>
    getCourseStatistics(courseId: string): Promise<Statistics>
  }

  validate: {
    checkAnswer(questionId: string, answer: string, mode: 'formative' | 'summative'): Promise<AnswerResult>
  }

  // v2.0 Topic-based access (NEW)
  knowledge: {
    getByTopic(topicPath: string): Promise<TopicIndex>
    getByDomain(domainId: string): Promise<Question[]>
    search(filters: KnowledgeFilters): Promise<Question[]>
  }

  taxonomy: {
    getDomains(): Promise<string[]>
    getTopics(): Promise<TaxonomyTree>
  }
}

Zod Schemas (Free Validation)

Import Zod schemas for offline validation:

import { QuestionSchema, CourseSchema } from '@telebort/question-banks/schemas'
import { z } from 'zod'

// Validate a question
const result = QuestionSchema.safeParse(myQuestion)
if (!result.success) {
  console.error(result.error.issues)
}

// Type inference
type Question = z.infer<typeof QuestionSchema>

Available Schemas

// Question schemas
QuestionSchema          // Full question with v1.1 enhancements
OptionSchema            // Answer option with misconception tracking
FeedbackSchema          // Structured feedback (short/detailed/socraticHint)

// Course schemas
CourseSchema            // Course with lessons and questions
LessonSchema            // Lesson with questions

// Assessment schemas
AssessmentSubmissionSchema  // User assessment submission
GradedAssessmentSchema      // Graded result with misconception analysis

CLI Tools

The SDK includes command-line tools for working with question bank data:

# Install globally
npm install -g @telebort/question-banks

# Or use via npx
npx @telebort/question-banks <command>

Commands

validate - Validate Course JSON Files

# Validate a single file
question-banks validate ./data/courses/ai-1.json

# Validate all files in a directory
question-banks validate ./data/courses/

# Show all validation errors
question-banks validate ./data/courses/ --verbose

stats - Show Statistics

# Show aggregate statistics
question-banks stats --data-dir ./data/courses/

# Show statistics for a specific course
question-banks stats --course ai-1 --data-dir ./data/courses/

quiz - Generate Sample Quizzes

# Generate 5 random questions
question-banks quiz --data-dir ./data/courses/

# Generate 10 questions from a specific course
question-banks quiz --course ai-1 --count 10 --data-dir ./data/courses/

# Filter by difficulty and show answers
question-banks quiz --difficulty hard --show-answers --data-dir ./data/courses/

Question Schema (v1.1)

Questions include v1.1 enhancements for misconception tracking:

interface Question {
  questionId: string           // "ai-1-l1-q1"
  globalId: string             // "exit-ticket-0351"
  questionType: QuestionType   // vocabulary, code_understanding, etc.
  questionArchetype?: string   // vocabulary, trace, bebras, blockmodel

  prompt: string
  hasCodeBlock: boolean
  codeLanguage: string | null
  codeContent: string | null

  // v1.1: Misconception targeting
  misconceptionTargets?: string[]

  options: Option[]            // 4 options with misconception feedback
  correctAnswer: 'A' | 'B' | 'C' | 'D'

  metadata: {
    difficulty: 'easy' | 'medium' | 'hard' | 'challenge'
    bloomsTaxonomy: 'remember' | 'understand' | 'apply' | ...
    tags: string[]
  }
}

interface Option {
  key: 'A' | 'B' | 'C' | 'D'
  text: string
  isCorrect: boolean

  // v1.1: Misconception feedback
  misconceptionId?: string     // "INPUT_PROMPT_VS_OUTPUT"
  feedback?: {
    short: string              // "Not quite! That's the prompt."
    detailed: string           // Full explanation
    socraticHint?: string      // "Where does the program display its result?"
  }
}

TypeScript Support

All types are inferred from Zod schemas:

import type {
  Question,
  Course,
  AssessmentSubmission,
  GradedAssessment
} from '@telebort/question-banks'

License

MIT


Support