@telebort/question-banks 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,96 @@
1
+ import { Question, Course } from '../schemas/index.cjs';
2
+ import { f as GradedAssessment, c as AssessmentSubmission } from '../assessment-EEJoYtXy.cjs';
3
+ import { Q as QuestionFilters, b as Statistics } from '../index-BPlb4Ksx.cjs';
4
+ import 'zod';
5
+
6
+ /**
7
+ * Configuration for PremiumClient
8
+ */
9
+ interface PremiumClientConfig {
10
+ token: string;
11
+ baseUrl?: string;
12
+ timeout?: number;
13
+ }
14
+ /**
15
+ * Question query options
16
+ */
17
+ interface GetQuestionsOptions extends QuestionFilters {
18
+ includeAnswers?: boolean;
19
+ }
20
+ /**
21
+ * Grading options
22
+ */
23
+ interface GradeOptions {
24
+ includeDetailedFeedback?: boolean;
25
+ includeMisconceptionAnalysis?: boolean;
26
+ passingThreshold?: number;
27
+ }
28
+ /**
29
+ * Premium API error
30
+ */
31
+ interface PremiumApiError {
32
+ code: 'UNAUTHORIZED' | 'TOKEN_EXPIRED' | 'RATE_LIMITED' | 'NOT_FOUND' | 'VALIDATION_ERROR' | 'SERVER_ERROR';
33
+ message: string;
34
+ retryAfter?: number;
35
+ }
36
+ /**
37
+ * Grading result with misconception analysis
38
+ */
39
+ interface GradingResult extends GradedAssessment {
40
+ recommendations?: string[];
41
+ }
42
+
43
+ /**
44
+ * Premium Tier - Full Access Client
45
+ *
46
+ * Provides full access to questions, grading, and analytics
47
+ * Requires JWT authentication
48
+ */
49
+ declare class PremiumClient {
50
+ private token;
51
+ private baseUrl;
52
+ private timeout;
53
+ constructor(config: PremiumClientConfig);
54
+ /**
55
+ * Fetch questions with full content (including answers)
56
+ */
57
+ getQuestions(options?: GetQuestionsOptions): Promise<{
58
+ questions: Question[];
59
+ total: number;
60
+ hasMore: boolean;
61
+ }>;
62
+ /**
63
+ * Get a single question by ID
64
+ */
65
+ getQuestion(questionId: string): Promise<Question | null>;
66
+ /**
67
+ * Get all courses
68
+ */
69
+ getCourses(): Promise<Course[]>;
70
+ /**
71
+ * Get a single course with all questions
72
+ */
73
+ getCourse(courseId: string): Promise<Course | null>;
74
+ /**
75
+ * Grade an assessment submission
76
+ *
77
+ * Returns detailed grading with misconception analysis
78
+ */
79
+ gradeAssessment(assessment: AssessmentSubmission, options?: GradeOptions): Promise<GradingResult>;
80
+ /**
81
+ * Get overall statistics
82
+ */
83
+ getStatistics(): Promise<Statistics>;
84
+ /**
85
+ * Get course-specific statistics
86
+ */
87
+ getCourseStatistics(courseId: string): Promise<Statistics & {
88
+ courseId: string;
89
+ }>;
90
+ /**
91
+ * Internal fetch wrapper with authentication
92
+ */
93
+ private fetch;
94
+ }
95
+
96
+ export { type GetQuestionsOptions, type GradeOptions, type GradingResult, type PremiumApiError, PremiumClient, type PremiumClientConfig };
@@ -0,0 +1,96 @@
1
+ import { Question, Course } from '../schemas/index.js';
2
+ import { f as GradedAssessment, c as AssessmentSubmission } from '../assessment-EEJoYtXy.js';
3
+ import { Q as QuestionFilters, b as Statistics } from '../index-BdbmdJgH.js';
4
+ import 'zod';
5
+
6
+ /**
7
+ * Configuration for PremiumClient
8
+ */
9
+ interface PremiumClientConfig {
10
+ token: string;
11
+ baseUrl?: string;
12
+ timeout?: number;
13
+ }
14
+ /**
15
+ * Question query options
16
+ */
17
+ interface GetQuestionsOptions extends QuestionFilters {
18
+ includeAnswers?: boolean;
19
+ }
20
+ /**
21
+ * Grading options
22
+ */
23
+ interface GradeOptions {
24
+ includeDetailedFeedback?: boolean;
25
+ includeMisconceptionAnalysis?: boolean;
26
+ passingThreshold?: number;
27
+ }
28
+ /**
29
+ * Premium API error
30
+ */
31
+ interface PremiumApiError {
32
+ code: 'UNAUTHORIZED' | 'TOKEN_EXPIRED' | 'RATE_LIMITED' | 'NOT_FOUND' | 'VALIDATION_ERROR' | 'SERVER_ERROR';
33
+ message: string;
34
+ retryAfter?: number;
35
+ }
36
+ /**
37
+ * Grading result with misconception analysis
38
+ */
39
+ interface GradingResult extends GradedAssessment {
40
+ recommendations?: string[];
41
+ }
42
+
43
+ /**
44
+ * Premium Tier - Full Access Client
45
+ *
46
+ * Provides full access to questions, grading, and analytics
47
+ * Requires JWT authentication
48
+ */
49
+ declare class PremiumClient {
50
+ private token;
51
+ private baseUrl;
52
+ private timeout;
53
+ constructor(config: PremiumClientConfig);
54
+ /**
55
+ * Fetch questions with full content (including answers)
56
+ */
57
+ getQuestions(options?: GetQuestionsOptions): Promise<{
58
+ questions: Question[];
59
+ total: number;
60
+ hasMore: boolean;
61
+ }>;
62
+ /**
63
+ * Get a single question by ID
64
+ */
65
+ getQuestion(questionId: string): Promise<Question | null>;
66
+ /**
67
+ * Get all courses
68
+ */
69
+ getCourses(): Promise<Course[]>;
70
+ /**
71
+ * Get a single course with all questions
72
+ */
73
+ getCourse(courseId: string): Promise<Course | null>;
74
+ /**
75
+ * Grade an assessment submission
76
+ *
77
+ * Returns detailed grading with misconception analysis
78
+ */
79
+ gradeAssessment(assessment: AssessmentSubmission, options?: GradeOptions): Promise<GradingResult>;
80
+ /**
81
+ * Get overall statistics
82
+ */
83
+ getStatistics(): Promise<Statistics>;
84
+ /**
85
+ * Get course-specific statistics
86
+ */
87
+ getCourseStatistics(courseId: string): Promise<Statistics & {
88
+ courseId: string;
89
+ }>;
90
+ /**
91
+ * Internal fetch wrapper with authentication
92
+ */
93
+ private fetch;
94
+ }
95
+
96
+ export { type GetQuestionsOptions, type GradeOptions, type GradingResult, type PremiumApiError, PremiumClient, type PremiumClientConfig };
@@ -0,0 +1,114 @@
1
+ // src/premium/client.ts
2
+ var PremiumClient = class {
3
+ constructor(config) {
4
+ this.token = config.token;
5
+ this.baseUrl = config.baseUrl ?? "https://api.telebort.com/exit-tickets/v1";
6
+ this.timeout = config.timeout ?? 3e4;
7
+ }
8
+ /**
9
+ * Fetch questions with full content (including answers)
10
+ */
11
+ async getQuestions(options) {
12
+ const params = new URLSearchParams();
13
+ if (options?.courseId) params.set("courseId", options.courseId);
14
+ if (options?.lessonNumber) params.set("lessonNumber", String(options.lessonNumber));
15
+ if (options?.questionType) params.set("questionType", options.questionType);
16
+ if (options?.difficulty) params.set("difficulty", options.difficulty);
17
+ if (options?.hasCodeBlock !== void 0) params.set("hasCodeBlock", String(options.hasCodeBlock));
18
+ if (options?.limit) params.set("limit", String(options.limit));
19
+ if (options?.offset) params.set("offset", String(options.offset));
20
+ const response = await this.fetch(`/questions?${params.toString()}`);
21
+ return await response.json();
22
+ }
23
+ /**
24
+ * Get a single question by ID
25
+ */
26
+ async getQuestion(questionId) {
27
+ try {
28
+ const response = await this.fetch(`/questions/${questionId}`);
29
+ const data = await response.json();
30
+ return data.question ?? null;
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+ /**
36
+ * Get all courses
37
+ */
38
+ async getCourses() {
39
+ const response = await this.fetch("/courses");
40
+ const data = await response.json();
41
+ return data.courses ?? [];
42
+ }
43
+ /**
44
+ * Get a single course with all questions
45
+ */
46
+ async getCourse(courseId) {
47
+ try {
48
+ const response = await this.fetch(`/courses/${courseId}`);
49
+ const data = await response.json();
50
+ return data.course ?? null;
51
+ } catch {
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Grade an assessment submission
57
+ *
58
+ * Returns detailed grading with misconception analysis
59
+ */
60
+ async gradeAssessment(assessment, options) {
61
+ const response = await this.fetch("/grade", {
62
+ method: "POST",
63
+ body: JSON.stringify({
64
+ assessment,
65
+ options: {
66
+ includeDetailedFeedback: options?.includeDetailedFeedback ?? true,
67
+ includeMisconceptionAnalysis: options?.includeMisconceptionAnalysis ?? true,
68
+ passingThreshold: options?.passingThreshold ?? 70
69
+ }
70
+ })
71
+ });
72
+ return await response.json();
73
+ }
74
+ /**
75
+ * Get overall statistics
76
+ */
77
+ async getStatistics() {
78
+ const response = await this.fetch("/analytics/statistics");
79
+ return await response.json();
80
+ }
81
+ /**
82
+ * Get course-specific statistics
83
+ */
84
+ async getCourseStatistics(courseId) {
85
+ const response = await this.fetch(`/analytics/courses/${courseId}`);
86
+ return await response.json();
87
+ }
88
+ /**
89
+ * Internal fetch wrapper with authentication
90
+ */
91
+ async fetch(path, init) {
92
+ const response = await fetch(`${this.baseUrl}${path}`, {
93
+ ...init,
94
+ headers: {
95
+ "Content-Type": "application/json",
96
+ "Authorization": `Bearer ${this.token}`,
97
+ ...init?.headers
98
+ },
99
+ signal: AbortSignal.timeout(this.timeout)
100
+ });
101
+ if (!response.ok) {
102
+ const error = await response.json().catch(() => ({
103
+ code: "SERVER_ERROR",
104
+ message: `HTTP ${response.status}: ${response.statusText}`
105
+ }));
106
+ throw new Error(`${error.code}: ${error.message}`);
107
+ }
108
+ return response;
109
+ }
110
+ };
111
+
112
+ export { PremiumClient };
113
+ //# sourceMappingURL=index.js.map
114
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/premium/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n Question,\n Course,\n AssessmentSubmission,\n} from '../schemas'\nimport type { Statistics } from '../types'\nimport type {\n PremiumClientConfig,\n GetQuestionsOptions,\n GradeOptions,\n GradingResult,\n PremiumApiError,\n} from './types'\n\n/**\n * Premium Tier - Full Access Client\n *\n * Provides full access to questions, grading, and analytics\n * Requires JWT authentication\n */\nexport class PremiumClient {\n private token: string\n private baseUrl: string\n private timeout: number\n\n constructor(config: PremiumClientConfig) {\n this.token = config.token\n this.baseUrl = config.baseUrl ?? 'https://api.telebort.com/exit-tickets/v1'\n this.timeout = config.timeout ?? 30000\n }\n\n /**\n * Fetch questions with full content (including answers)\n */\n async getQuestions(options?: GetQuestionsOptions): Promise<{\n questions: Question[]\n total: number\n hasMore: boolean\n }> {\n const params = new URLSearchParams()\n\n if (options?.courseId) params.set('courseId', options.courseId)\n if (options?.lessonNumber) params.set('lessonNumber', String(options.lessonNumber))\n if (options?.questionType) params.set('questionType', options.questionType)\n if (options?.difficulty) params.set('difficulty', options.difficulty)\n if (options?.hasCodeBlock !== undefined) params.set('hasCodeBlock', String(options.hasCodeBlock))\n if (options?.limit) params.set('limit', String(options.limit))\n if (options?.offset) params.set('offset', String(options.offset))\n\n const response = await this.fetch(`/questions?${params.toString()}`)\n return await response.json() as { questions: Question[]; total: number; hasMore: boolean }\n }\n\n /**\n * Get a single question by ID\n */\n async getQuestion(questionId: string): Promise<Question | null> {\n try {\n const response = await this.fetch(`/questions/${questionId}`)\n const data = await response.json() as { question?: Question }\n return data.question ?? null\n } catch {\n return null\n }\n }\n\n /**\n * Get all courses\n */\n async getCourses(): Promise<Course[]> {\n const response = await this.fetch('/courses')\n const data = await response.json() as { courses?: Course[] }\n return data.courses ?? []\n }\n\n /**\n * Get a single course with all questions\n */\n async getCourse(courseId: string): Promise<Course | null> {\n try {\n const response = await this.fetch(`/courses/${courseId}`)\n const data = await response.json() as { course?: Course }\n return data.course ?? null\n } catch {\n return null\n }\n }\n\n /**\n * Grade an assessment submission\n *\n * Returns detailed grading with misconception analysis\n */\n async gradeAssessment(\n assessment: AssessmentSubmission,\n options?: GradeOptions\n ): Promise<GradingResult> {\n const response = await this.fetch('/grade', {\n method: 'POST',\n body: JSON.stringify({\n assessment,\n options: {\n includeDetailedFeedback: options?.includeDetailedFeedback ?? true,\n includeMisconceptionAnalysis: options?.includeMisconceptionAnalysis ?? true,\n passingThreshold: options?.passingThreshold ?? 70,\n },\n }),\n })\n\n return await response.json() as GradingResult\n }\n\n /**\n * Get overall statistics\n */\n async getStatistics(): Promise<Statistics> {\n const response = await this.fetch('/analytics/statistics')\n return await response.json() as Statistics\n }\n\n /**\n * Get course-specific statistics\n */\n async getCourseStatistics(courseId: string): Promise<Statistics & { courseId: string }> {\n const response = await this.fetch(`/analytics/courses/${courseId}`)\n return await response.json() as Statistics & { courseId: string }\n }\n\n /**\n * Internal fetch wrapper with authentication\n */\n private async fetch(path: string, init?: RequestInit): Promise<Response> {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.token}`,\n ...init?.headers,\n },\n signal: AbortSignal.timeout(this.timeout),\n })\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({\n code: 'SERVER_ERROR',\n message: `HTTP ${response.status}: ${response.statusText}`,\n })) as PremiumApiError\n\n throw new Error(`${error.code}: ${error.message}`)\n }\n\n return response\n }\n}\n"]}
@@ -0,0 +1,242 @@
1
+ 'use strict';
2
+
3
+ var zod = require('zod');
4
+
5
+ // src/schemas/question.ts
6
+ var FeedbackSchema = zod.z.object({
7
+ short: zod.z.string().min(1).max(200),
8
+ detailed: zod.z.string().min(1).max(1e3),
9
+ socraticHint: zod.z.string().max(300).optional()
10
+ });
11
+ var OptionKeySchema = zod.z.enum(["A", "B", "C", "D"]);
12
+ var OptionSchema = zod.z.object({
13
+ key: OptionKeySchema,
14
+ text: zod.z.string().min(1),
15
+ isCorrect: zod.z.boolean(),
16
+ // v1.1 fields - optional for backward compatibility
17
+ misconceptionId: zod.z.string().optional(),
18
+ feedback: FeedbackSchema.optional()
19
+ });
20
+ var QuestionTypeSchema = zod.z.enum([
21
+ "vocabulary",
22
+ "code_understanding",
23
+ "problem_solving",
24
+ "application",
25
+ "reflection"
26
+ ]);
27
+ var QuestionArchetypeSchema = zod.z.enum([
28
+ "vocabulary",
29
+ "trace",
30
+ "bebras",
31
+ "blockmodel",
32
+ "parsons"
33
+ ]);
34
+ var DifficultySchema = zod.z.enum(["easy", "medium", "hard", "challenge"]);
35
+ var BloomsTaxonomySchema = zod.z.enum([
36
+ "remember",
37
+ "understand",
38
+ "apply",
39
+ "analyze",
40
+ "evaluate",
41
+ "create"
42
+ ]);
43
+ var QuestionMetadataSchema = zod.z.object({
44
+ difficulty: DifficultySchema,
45
+ estimatedTime: zod.z.number().int().positive(),
46
+ // seconds
47
+ bloomsTaxonomy: BloomsTaxonomySchema,
48
+ tags: zod.z.array(zod.z.string()),
49
+ source: zod.z.string().default("exit-ticket"),
50
+ version: zod.z.string().default("1.1"),
51
+ createdDate: zod.z.string().optional(),
52
+ lastModified: zod.z.string().optional()
53
+ });
54
+ var QuestionSchema = zod.z.object({
55
+ // Identifiers
56
+ questionId: zod.z.string().regex(/^[a-z0-9-]+-l\d+-q\d+$/),
57
+ globalId: zod.z.string().regex(/^exit-ticket-\d{4}$/),
58
+ questionNumber: zod.z.number().int().positive().max(5),
59
+ // Classification
60
+ questionType: QuestionTypeSchema,
61
+ questionTypeLabel: zod.z.string(),
62
+ questionArchetype: QuestionArchetypeSchema.optional(),
63
+ // v1.1
64
+ // Content
65
+ prompt: zod.z.string().min(10),
66
+ hasCodeBlock: zod.z.boolean(),
67
+ codeLanguage: zod.z.string().nullable(),
68
+ codeContent: zod.z.string().nullable(),
69
+ // Misconception targeting (v1.1)
70
+ misconceptionTargets: zod.z.array(zod.z.string()).optional(),
71
+ // Answer options (exactly 4)
72
+ options: zod.z.array(OptionSchema).length(4),
73
+ // Correct answer
74
+ correctAnswer: OptionKeySchema,
75
+ correctAnswerText: zod.z.string(),
76
+ // Metadata
77
+ metadata: QuestionMetadataSchema
78
+ });
79
+ var QuestionWithoutAnswerSchema = QuestionSchema.omit({
80
+ correctAnswer: true,
81
+ correctAnswerText: true
82
+ }).extend({
83
+ options: zod.z.array(
84
+ OptionSchema.omit({
85
+ isCorrect: true,
86
+ feedback: true,
87
+ misconceptionId: true
88
+ })
89
+ ).length(4)
90
+ });
91
+ var CourseDomainSchema = zod.z.enum([
92
+ // AI & Data Science
93
+ "ai_data_science",
94
+ "ai_ml_cv",
95
+ "ai_generative",
96
+ "ai_advanced",
97
+ // Web Development
98
+ "web_development",
99
+ // Mobile Development
100
+ "mobile_development",
101
+ "mobile",
102
+ // Block-based Programming
103
+ "block_based",
104
+ "python_programming",
105
+ "design",
106
+ // Foundation
107
+ "foundation",
108
+ "creative_computing"
109
+ ]);
110
+ var CourseTierSchema = zod.z.enum([
111
+ "foundation",
112
+ "intermediate",
113
+ "advanced"
114
+ ]);
115
+ var LessonSchema = zod.z.object({
116
+ lessonId: zod.z.string(),
117
+ // e.g., "ai-1-lesson-1"
118
+ lessonNumber: zod.z.number().int().positive(),
119
+ lessonTitle: zod.z.string(),
120
+ lessonSlug: zod.z.string().optional(),
121
+ totalQuestions: zod.z.number().int().positive().default(5),
122
+ questions: zod.z.array(QuestionSchema)
123
+ });
124
+ var CourseSchema = zod.z.object({
125
+ courseId: zod.z.string(),
126
+ // e.g., "ai-1"
127
+ courseName: zod.z.string(),
128
+ // e.g., "AI-1 Data Analysis and Data Science"
129
+ courseCode: zod.z.string(),
130
+ // e.g., "AI1"
131
+ domain: CourseDomainSchema,
132
+ tier: CourseTierSchema,
133
+ difficulty: zod.z.number().int().min(1).max(5),
134
+ totalLessons: zod.z.number().int().positive(),
135
+ totalQuestions: zod.z.number().int().positive(),
136
+ sourceFile: zod.z.string().optional(),
137
+ lessons: zod.z.array(LessonSchema)
138
+ });
139
+ var CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({
140
+ lessons: zod.z.array(
141
+ LessonSchema.omit({ questions: true })
142
+ ).optional()
143
+ });
144
+ var UserResponseSchema = zod.z.object({
145
+ questionId: zod.z.string(),
146
+ selectedAnswer: OptionKeySchema,
147
+ timeSpent: zod.z.number().int().nonnegative().optional(),
148
+ // milliseconds
149
+ submittedAt: zod.z.string().datetime().optional()
150
+ });
151
+ var AssessmentSubmissionSchema = zod.z.object({
152
+ assessmentId: zod.z.string().uuid().optional(),
153
+ // Generated if not provided
154
+ userId: zod.z.string().optional(),
155
+ // For authenticated users
156
+ sessionId: zod.z.string().optional(),
157
+ // For anonymous sessions
158
+ courseId: zod.z.string(),
159
+ lessonId: zod.z.string().optional(),
160
+ responses: zod.z.array(UserResponseSchema).min(1),
161
+ submittedAt: zod.z.string().datetime(),
162
+ metadata: zod.z.record(zod.z.unknown()).optional()
163
+ // Custom metadata
164
+ });
165
+ var GradedResponseSchema = zod.z.object({
166
+ questionId: zod.z.string(),
167
+ selectedAnswer: OptionKeySchema,
168
+ correctAnswer: OptionKeySchema,
169
+ isCorrect: zod.z.boolean(),
170
+ misconceptionId: zod.z.string().nullable(),
171
+ // For incorrect answers
172
+ feedback: FeedbackSchema.optional(),
173
+ timeSpent: zod.z.number().int().nonnegative().optional()
174
+ });
175
+ var MisconceptionReportSchema = zod.z.object({
176
+ misconceptionId: zod.z.string(),
177
+ count: zod.z.number().int().positive(),
178
+ percentage: zod.z.number().min(0).max(100),
179
+ questionIds: zod.z.array(zod.z.string()),
180
+ description: zod.z.string().optional()
181
+ });
182
+ var GradedAssessmentSchema = zod.z.object({
183
+ assessmentId: zod.z.string().uuid(),
184
+ userId: zod.z.string().optional(),
185
+ courseId: zod.z.string(),
186
+ lessonId: zod.z.string().optional(),
187
+ // Scores
188
+ totalQuestions: zod.z.number().int().positive(),
189
+ correctCount: zod.z.number().int().nonnegative(),
190
+ incorrectCount: zod.z.number().int().nonnegative(),
191
+ score: zod.z.number().min(0).max(100),
192
+ // Percentage
193
+ passed: zod.z.boolean(),
194
+ // Based on threshold (default 70%)
195
+ // Detailed results
196
+ responses: zod.z.array(GradedResponseSchema),
197
+ // Misconception analysis (v1.1 feature)
198
+ misconceptions: zod.z.array(MisconceptionReportSchema).optional(),
199
+ topMisconceptions: zod.z.array(zod.z.string()).max(3).optional(),
200
+ // Timing
201
+ totalTimeSpent: zod.z.number().int().nonnegative().optional(),
202
+ // milliseconds
203
+ averageTimePerQuestion: zod.z.number().nonnegative().optional(),
204
+ submittedAt: zod.z.string().datetime(),
205
+ gradedAt: zod.z.string().datetime()
206
+ });
207
+ var ValidationResultSchema = zod.z.object({
208
+ valid: zod.z.boolean(),
209
+ errors: zod.z.array(zod.z.object({
210
+ path: zod.z.array(zod.z.union([zod.z.string(), zod.z.number()])),
211
+ message: zod.z.string(),
212
+ code: zod.z.string().optional()
213
+ })).optional(),
214
+ isComplete: zod.z.boolean(),
215
+ // All questions answered
216
+ questionCount: zod.z.number().int(),
217
+ answeredCount: zod.z.number().int()
218
+ });
219
+
220
+ exports.AssessmentSubmissionSchema = AssessmentSubmissionSchema;
221
+ exports.BloomsTaxonomySchema = BloomsTaxonomySchema;
222
+ exports.CourseDomainSchema = CourseDomainSchema;
223
+ exports.CourseSchema = CourseSchema;
224
+ exports.CourseSummarySchema = CourseSummarySchema;
225
+ exports.CourseTierSchema = CourseTierSchema;
226
+ exports.DifficultySchema = DifficultySchema;
227
+ exports.FeedbackSchema = FeedbackSchema;
228
+ exports.GradedAssessmentSchema = GradedAssessmentSchema;
229
+ exports.GradedResponseSchema = GradedResponseSchema;
230
+ exports.LessonSchema = LessonSchema;
231
+ exports.MisconceptionReportSchema = MisconceptionReportSchema;
232
+ exports.OptionKeySchema = OptionKeySchema;
233
+ exports.OptionSchema = OptionSchema;
234
+ exports.QuestionArchetypeSchema = QuestionArchetypeSchema;
235
+ exports.QuestionMetadataSchema = QuestionMetadataSchema;
236
+ exports.QuestionSchema = QuestionSchema;
237
+ exports.QuestionTypeSchema = QuestionTypeSchema;
238
+ exports.QuestionWithoutAnswerSchema = QuestionWithoutAnswerSchema;
239
+ exports.UserResponseSchema = UserResponseSchema;
240
+ exports.ValidationResultSchema = ValidationResultSchema;
241
+ //# sourceMappingURL=index.cjs.map
242
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/schemas/question.ts","../../src/schemas/course.ts","../../src/schemas/assessment.ts"],"names":["z"],"mappings":"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","file":"index.cjs","sourcesContent":["import { z } from 'zod'\n\n// ============================================================================\n// Feedback Schema (v1.1 enhancement)\n// ============================================================================\n\n/**\n * Structured feedback following the \"Not Yet\" protocol\n * - short: Brief acknowledgment (1 sentence)\n * - detailed: Full explanation of the misconception\n * - socraticHint: Optional guiding question for discovery learning\n */\nexport const FeedbackSchema = z.object({\n short: z.string().min(1).max(200),\n detailed: z.string().min(1).max(1000),\n socraticHint: z.string().max(300).optional(),\n})\n\nexport type Feedback = z.infer<typeof FeedbackSchema>\n\n// ============================================================================\n// Option Schema\n// ============================================================================\n\nexport const OptionKeySchema = z.enum(['A', 'B', 'C', 'D'])\n\nexport type OptionKey = z.infer<typeof OptionKeySchema>\n\n/**\n * Answer option with optional misconception tracking (v1.1)\n */\nexport const OptionSchema = z.object({\n key: OptionKeySchema,\n text: z.string().min(1),\n isCorrect: z.boolean(),\n // v1.1 fields - optional for backward compatibility\n misconceptionId: z.string().optional(),\n feedback: FeedbackSchema.optional(),\n})\n\nexport type Option = z.infer<typeof OptionSchema>\n\n// ============================================================================\n// Question Type Enums\n// ============================================================================\n\nexport const QuestionTypeSchema = z.enum([\n 'vocabulary',\n 'code_understanding',\n 'problem_solving',\n 'application',\n 'reflection',\n])\n\nexport type QuestionType = z.infer<typeof QuestionTypeSchema>\n\n/**\n * Question archetype for pedagogical classification\n * - vocabulary: Definition/terminology questions\n * - trace: Code tracing (mental execution)\n * - bebras: Logic-first, computational thinking\n * - blockmodel: Surface/flow/purpose analysis\n * - parsons: Code block reordering (future)\n */\nexport const QuestionArchetypeSchema = z.enum([\n 'vocabulary',\n 'trace',\n 'bebras',\n 'blockmodel',\n 'parsons',\n])\n\nexport type QuestionArchetype = z.infer<typeof QuestionArchetypeSchema>\n\nexport const DifficultySchema = z.enum(['easy', 'medium', 'hard', 'challenge'])\n\nexport type Difficulty = z.infer<typeof DifficultySchema>\n\nexport const BloomsTaxonomySchema = z.enum([\n 'remember',\n 'understand',\n 'apply',\n 'analyze',\n 'evaluate',\n 'create',\n])\n\nexport type BloomsTaxonomy = z.infer<typeof BloomsTaxonomySchema>\n\n// ============================================================================\n// Question Metadata Schema\n// ============================================================================\n\nexport const QuestionMetadataSchema = z.object({\n difficulty: DifficultySchema,\n estimatedTime: z.number().int().positive(), // seconds\n bloomsTaxonomy: BloomsTaxonomySchema,\n tags: z.array(z.string()),\n source: z.string().default('exit-ticket'),\n version: z.string().default('1.1'),\n createdDate: z.string().optional(),\n lastModified: z.string().optional(),\n})\n\nexport type QuestionMetadata = z.infer<typeof QuestionMetadataSchema>\n\n// ============================================================================\n// Question Schema (v1.1)\n// ============================================================================\n\n/**\n * Full question schema with v1.1 enhancements:\n * - questionArchetype: Pedagogical classification\n * - misconceptionTargets: Expected misconceptions this question probes\n * - options with misconceptionId and structured feedback\n */\nexport const QuestionSchema = z.object({\n // Identifiers\n questionId: z.string().regex(/^[a-z0-9-]+-l\\d+-q\\d+$/),\n globalId: z.string().regex(/^exit-ticket-\\d{4}$/),\n questionNumber: z.number().int().positive().max(5),\n\n // Classification\n questionType: QuestionTypeSchema,\n questionTypeLabel: z.string(),\n questionArchetype: QuestionArchetypeSchema.optional(), // v1.1\n\n // Content\n prompt: z.string().min(10),\n hasCodeBlock: z.boolean(),\n codeLanguage: z.string().nullable(),\n codeContent: z.string().nullable(),\n\n // Misconception targeting (v1.1)\n misconceptionTargets: z.array(z.string()).optional(),\n\n // Answer options (exactly 4)\n options: z.array(OptionSchema).length(4),\n\n // Correct answer\n correctAnswer: OptionKeySchema,\n correctAnswerText: z.string(),\n\n // Metadata\n metadata: QuestionMetadataSchema,\n})\n\nexport type Question = z.infer<typeof QuestionSchema>\n\n// ============================================================================\n// Question without answer (for Standard tier - no answer leakage)\n// ============================================================================\n\nexport const QuestionWithoutAnswerSchema = QuestionSchema.omit({\n correctAnswer: true,\n correctAnswerText: true,\n}).extend({\n options: z.array(\n OptionSchema.omit({\n isCorrect: true,\n feedback: true,\n misconceptionId: true,\n })\n ).length(4),\n})\n\nexport type QuestionWithoutAnswer = z.infer<typeof QuestionWithoutAnswerSchema>\n","import { z } from 'zod'\nimport { QuestionSchema } from './question'\n\n// ============================================================================\n// Course Domain & Tier\n// ============================================================================\n\nexport const CourseDomainSchema = z.enum([\n // AI & Data Science\n 'ai_data_science',\n 'ai_ml_cv',\n 'ai_generative',\n 'ai_advanced',\n // Web Development\n 'web_development',\n // Mobile Development\n 'mobile_development',\n 'mobile',\n // Block-based Programming\n 'block_based',\n 'python_programming',\n 'design',\n // Foundation\n 'foundation',\n 'creative_computing',\n])\n\nexport type CourseDomain = z.infer<typeof CourseDomainSchema>\n\nexport const CourseTierSchema = z.enum([\n 'foundation',\n 'intermediate',\n 'advanced',\n])\n\nexport type CourseTier = z.infer<typeof CourseTierSchema>\n\n// ============================================================================\n// Lesson Schema\n// ============================================================================\n\nexport const LessonSchema = z.object({\n lessonId: z.string(), // e.g., \"ai-1-lesson-1\"\n lessonNumber: z.number().int().positive(),\n lessonTitle: z.string(),\n lessonSlug: z.string().optional(),\n totalQuestions: z.number().int().positive().default(5),\n questions: z.array(QuestionSchema),\n})\n\nexport type Lesson = z.infer<typeof LessonSchema>\n\n// ============================================================================\n// Course Schema\n// ============================================================================\n\nexport const CourseSchema = z.object({\n courseId: z.string(), // e.g., \"ai-1\"\n courseName: z.string(), // e.g., \"AI-1 Data Analysis and Data Science\"\n courseCode: z.string(), // e.g., \"AI1\"\n domain: CourseDomainSchema,\n tier: CourseTierSchema,\n difficulty: z.number().int().min(1).max(5),\n totalLessons: z.number().int().positive(),\n totalQuestions: z.number().int().positive(),\n sourceFile: z.string().optional(),\n lessons: z.array(LessonSchema),\n})\n\nexport type Course = z.infer<typeof CourseSchema>\n\n// ============================================================================\n// Course Summary (without questions - for listing)\n// ============================================================================\n\nexport const CourseSummarySchema = CourseSchema.omit({ lessons: true }).extend({\n lessons: z.array(\n LessonSchema.omit({ questions: true })\n ).optional(),\n})\n\nexport type CourseSummary = z.infer<typeof CourseSummarySchema>\n","import { z } from 'zod'\nimport { OptionKeySchema, FeedbackSchema } from './question'\n\n// ============================================================================\n// User Response Schema\n// ============================================================================\n\n/**\n * A single user response to a question\n */\nexport const UserResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n timeSpent: z.number().int().nonnegative().optional(), // milliseconds\n submittedAt: z.string().datetime().optional(),\n})\n\nexport type UserResponse = z.infer<typeof UserResponseSchema>\n\n// ============================================================================\n// Assessment Submission Schema\n// ============================================================================\n\n/**\n * An assessment submission containing multiple responses\n */\nexport const AssessmentSubmissionSchema = z.object({\n assessmentId: z.string().uuid().optional(), // Generated if not provided\n userId: z.string().optional(), // For authenticated users\n sessionId: z.string().optional(), // For anonymous sessions\n courseId: z.string(),\n lessonId: z.string().optional(),\n responses: z.array(UserResponseSchema).min(1),\n submittedAt: z.string().datetime(),\n metadata: z.record(z.unknown()).optional(), // Custom metadata\n})\n\nexport type AssessmentSubmission = z.infer<typeof AssessmentSubmissionSchema>\n\n// ============================================================================\n// Graded Response Schema (Premium tier)\n// ============================================================================\n\n/**\n * Result of grading a single response\n */\nexport const GradedResponseSchema = z.object({\n questionId: z.string(),\n selectedAnswer: OptionKeySchema,\n correctAnswer: OptionKeySchema,\n isCorrect: z.boolean(),\n misconceptionId: z.string().nullable(), // For incorrect answers\n feedback: FeedbackSchema.optional(),\n timeSpent: z.number().int().nonnegative().optional(),\n})\n\nexport type GradedResponse = z.infer<typeof GradedResponseSchema>\n\n// ============================================================================\n// Misconception Report Schema (Premium tier)\n// ============================================================================\n\n/**\n * Aggregated misconception analysis for an assessment\n */\nexport const MisconceptionReportSchema = z.object({\n misconceptionId: z.string(),\n count: z.number().int().positive(),\n percentage: z.number().min(0).max(100),\n questionIds: z.array(z.string()),\n description: z.string().optional(),\n})\n\nexport type MisconceptionReport = z.infer<typeof MisconceptionReportSchema>\n\n// ============================================================================\n// Graded Assessment Schema (Premium tier)\n// ============================================================================\n\n/**\n * Complete graded assessment with scores and misconception analysis\n */\nexport const GradedAssessmentSchema = z.object({\n assessmentId: z.string().uuid(),\n userId: z.string().optional(),\n courseId: z.string(),\n lessonId: z.string().optional(),\n\n // Scores\n totalQuestions: z.number().int().positive(),\n correctCount: z.number().int().nonnegative(),\n incorrectCount: z.number().int().nonnegative(),\n score: z.number().min(0).max(100), // Percentage\n passed: z.boolean(), // Based on threshold (default 70%)\n\n // Detailed results\n responses: z.array(GradedResponseSchema),\n\n // Misconception analysis (v1.1 feature)\n misconceptions: z.array(MisconceptionReportSchema).optional(),\n topMisconceptions: z.array(z.string()).max(3).optional(),\n\n // Timing\n totalTimeSpent: z.number().int().nonnegative().optional(), // milliseconds\n averageTimePerQuestion: z.number().nonnegative().optional(),\n submittedAt: z.string().datetime(),\n gradedAt: z.string().datetime(),\n})\n\nexport type GradedAssessment = z.infer<typeof GradedAssessmentSchema>\n\n// ============================================================================\n// Validation Result Schema (Standard tier - no answer leakage)\n// ============================================================================\n\n/**\n * Result of validating an assessment submission\n * Does NOT reveal correct answers - only schema compliance\n */\nexport const ValidationResultSchema = z.object({\n valid: z.boolean(),\n errors: z.array(z.object({\n path: z.array(z.union([z.string(), z.number()])),\n message: z.string(),\n code: z.string().optional(),\n })).optional(),\n isComplete: z.boolean(), // All questions answered\n questionCount: z.number().int(),\n answeredCount: z.number().int(),\n})\n\nexport type ValidationResult = z.infer<typeof ValidationResultSchema>\n"]}