@anantagnanam/lms 0.1.0 → 0.3.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.
- package/LICENSE +21 -21
- package/README.md +40 -2
- package/astro/assignment-player.ts +231 -0
- package/astro/client.ts +97 -152
- package/astro/components/AssignmentFeedback.astro +32 -0
- package/astro/components/AssignmentRubric.astro +27 -0
- package/astro/components/CourseOverview.astro +25 -3
- package/astro/components/LearnerDashboard.astro +9 -0
- package/astro/components/LearningShell.astro +16 -1
- package/astro/components/LessonAvailabilityNote.astro +26 -0
- package/astro/components/LessonContent.astro +67 -0
- package/astro/components/LessonPlayer.astro +166 -99
- package/astro/components/MediaPlayer.astro +55 -4
- package/astro/draft-queue.ts +95 -0
- package/astro/media-player.ts +124 -0
- package/astro/pages/author-preview.astro +73 -0
- package/astro/pages/course.astro +10 -0
- package/astro/pages/lesson.astro +3 -0
- package/astro/pages/library.astro +173 -0
- package/astro/pages/paths.astro +73 -0
- package/astro/pages/study.astro +180 -0
- package/astro/quiz-drafts.ts +23 -0
- package/astro/quiz-player.ts +362 -0
- package/astro/study-tools.ts +386 -0
- package/astro/styles.css +30 -0
- package/astro/transcript-search.ts +56 -0
- package/dist/admin.d.ts +3 -1
- package/dist/admin.js +756 -127
- package/dist/admin.js.map +1 -1
- package/dist/assignments-CsuAjxGO.js +75 -0
- package/dist/assignments-CsuAjxGO.js.map +1 -0
- package/dist/astro.js +4 -0
- package/dist/astro.js.map +1 -1
- package/dist/{constants-C0kT94tc.js → constants-DyQbwNbP.js} +25 -3
- package/dist/constants-DyQbwNbP.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/runtime.d.ts +129 -16
- package/dist/runtime.js +1201 -130
- package/dist/runtime.js.map +1 -1
- package/dist/schemas.d.ts +136 -3
- package/dist/schemas.js +80 -7
- package/dist/schemas.js.map +1 -1
- package/dist/server.d.ts +18 -1
- package/dist/server.js +17 -3
- package/dist/server.js.map +1 -1
- package/dist/types.d.ts +172 -4
- package/package.json +1 -1
- package/dist/constants-C0kT94tc.js.map +0 -1
- package/dist/errors-ChzJS9al.js +0 -16
- package/dist/errors-ChzJS9al.js.map +0 -1
package/dist/schemas.d.ts
CHANGED
|
@@ -56,12 +56,29 @@ declare const quizSchema: z.ZodObject<{
|
|
|
56
56
|
after_submit: "after_submit";
|
|
57
57
|
}>>;
|
|
58
58
|
}, z.core.$strip>;
|
|
59
|
+
declare const rubricCriterionSchema: z.ZodObject<{
|
|
60
|
+
id: z.ZodString;
|
|
61
|
+
title: z.ZodString;
|
|
62
|
+
description: z.ZodDefault<z.ZodString>;
|
|
63
|
+
maxPoints: z.ZodNumber;
|
|
64
|
+
}, z.core.$strip>;
|
|
65
|
+
declare const rubricScoreSchema: z.ZodObject<{
|
|
66
|
+
criterionId: z.ZodString;
|
|
67
|
+
points: z.ZodNumber;
|
|
68
|
+
feedback: z.ZodDefault<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>;
|
|
59
70
|
declare const assignmentSchema: z.ZodObject<{
|
|
60
71
|
instructions: z.ZodString;
|
|
61
72
|
maxPoints: z.ZodDefault<z.ZodNumber>;
|
|
62
73
|
passingPoints: z.ZodDefault<z.ZodNumber>;
|
|
63
74
|
dueAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
64
75
|
allowResubmission: z.ZodDefault<z.ZodBoolean>;
|
|
76
|
+
rubric: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
77
|
+
id: z.ZodString;
|
|
78
|
+
title: z.ZodString;
|
|
79
|
+
description: z.ZodDefault<z.ZodString>;
|
|
80
|
+
maxPoints: z.ZodNumber;
|
|
81
|
+
}, z.core.$strip>>>;
|
|
65
82
|
}, z.core.$strip>;
|
|
66
83
|
declare const lessonSchema: z.ZodObject<{
|
|
67
84
|
id: z.ZodString;
|
|
@@ -83,6 +100,12 @@ declare const lessonSchema: z.ZodObject<{
|
|
|
83
100
|
field: z.ZodDefault<z.ZodString>;
|
|
84
101
|
}, z.core.$strip>>>;
|
|
85
102
|
mediaUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
103
|
+
transcript: z.ZodDefault<z.ZodString>;
|
|
104
|
+
captions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
105
|
+
src: z.ZodString;
|
|
106
|
+
language: z.ZodString;
|
|
107
|
+
label: z.ZodString;
|
|
108
|
+
}, z.core.$strip>>>;
|
|
86
109
|
liveStartsAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
87
110
|
durationMinutes: z.ZodDefault<z.ZodNumber>;
|
|
88
111
|
minStudySeconds: z.ZodDefault<z.ZodNumber>;
|
|
@@ -129,6 +152,12 @@ declare const lessonSchema: z.ZodObject<{
|
|
|
129
152
|
passingPoints: z.ZodDefault<z.ZodNumber>;
|
|
130
153
|
dueAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
131
154
|
allowResubmission: z.ZodDefault<z.ZodBoolean>;
|
|
155
|
+
rubric: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
156
|
+
id: z.ZodString;
|
|
157
|
+
title: z.ZodString;
|
|
158
|
+
description: z.ZodDefault<z.ZodString>;
|
|
159
|
+
maxPoints: z.ZodNumber;
|
|
160
|
+
}, z.core.$strip>>>;
|
|
132
161
|
}, z.core.$strip>>>;
|
|
133
162
|
}, z.core.$strip>;
|
|
134
163
|
declare const moduleSchema: z.ZodObject<{
|
|
@@ -157,6 +186,12 @@ declare const moduleSchema: z.ZodObject<{
|
|
|
157
186
|
field: z.ZodDefault<z.ZodString>;
|
|
158
187
|
}, z.core.$strip>>>;
|
|
159
188
|
mediaUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
189
|
+
transcript: z.ZodDefault<z.ZodString>;
|
|
190
|
+
captions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
191
|
+
src: z.ZodString;
|
|
192
|
+
language: z.ZodString;
|
|
193
|
+
label: z.ZodString;
|
|
194
|
+
}, z.core.$strip>>>;
|
|
160
195
|
liveStartsAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
161
196
|
durationMinutes: z.ZodDefault<z.ZodNumber>;
|
|
162
197
|
minStudySeconds: z.ZodDefault<z.ZodNumber>;
|
|
@@ -203,6 +238,12 @@ declare const moduleSchema: z.ZodObject<{
|
|
|
203
238
|
passingPoints: z.ZodDefault<z.ZodNumber>;
|
|
204
239
|
dueAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
205
240
|
allowResubmission: z.ZodDefault<z.ZodBoolean>;
|
|
241
|
+
rubric: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
242
|
+
id: z.ZodString;
|
|
243
|
+
title: z.ZodString;
|
|
244
|
+
description: z.ZodDefault<z.ZodString>;
|
|
245
|
+
maxPoints: z.ZodNumber;
|
|
246
|
+
}, z.core.$strip>>>;
|
|
206
247
|
}, z.core.$strip>>>;
|
|
207
248
|
}, z.core.$strip>>>;
|
|
208
249
|
}, z.core.$strip>;
|
|
@@ -279,6 +320,12 @@ declare const courseDataSchema: z.ZodObject<{
|
|
|
279
320
|
field: z.ZodDefault<z.ZodString>;
|
|
280
321
|
}, z.core.$strip>>>;
|
|
281
322
|
mediaUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
323
|
+
transcript: z.ZodDefault<z.ZodString>;
|
|
324
|
+
captions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
325
|
+
src: z.ZodString;
|
|
326
|
+
language: z.ZodString;
|
|
327
|
+
label: z.ZodString;
|
|
328
|
+
}, z.core.$strip>>>;
|
|
282
329
|
liveStartsAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
283
330
|
durationMinutes: z.ZodDefault<z.ZodNumber>;
|
|
284
331
|
minStudySeconds: z.ZodDefault<z.ZodNumber>;
|
|
@@ -325,6 +372,12 @@ declare const courseDataSchema: z.ZodObject<{
|
|
|
325
372
|
passingPoints: z.ZodDefault<z.ZodNumber>;
|
|
326
373
|
dueAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
327
374
|
allowResubmission: z.ZodDefault<z.ZodBoolean>;
|
|
375
|
+
rubric: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
376
|
+
id: z.ZodString;
|
|
377
|
+
title: z.ZodString;
|
|
378
|
+
description: z.ZodDefault<z.ZodString>;
|
|
379
|
+
maxPoints: z.ZodNumber;
|
|
380
|
+
}, z.core.$strip>>>;
|
|
328
381
|
}, z.core.$strip>>>;
|
|
329
382
|
}, z.core.$strip>>>;
|
|
330
383
|
}, z.core.$strip>>>;
|
|
@@ -405,6 +458,12 @@ declare const courseSaveSchema: z.ZodObject<{
|
|
|
405
458
|
field: z.ZodDefault<z.ZodString>;
|
|
406
459
|
}, z.core.$strip>>>;
|
|
407
460
|
mediaUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
461
|
+
transcript: z.ZodDefault<z.ZodString>;
|
|
462
|
+
captions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
463
|
+
src: z.ZodString;
|
|
464
|
+
language: z.ZodString;
|
|
465
|
+
label: z.ZodString;
|
|
466
|
+
}, z.core.$strip>>>;
|
|
408
467
|
liveStartsAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
409
468
|
durationMinutes: z.ZodDefault<z.ZodNumber>;
|
|
410
469
|
minStudySeconds: z.ZodDefault<z.ZodNumber>;
|
|
@@ -451,6 +510,12 @@ declare const courseSaveSchema: z.ZodObject<{
|
|
|
451
510
|
passingPoints: z.ZodDefault<z.ZodNumber>;
|
|
452
511
|
dueAt: z.ZodDefault<z.ZodNullable<z.ZodISODateTime>>;
|
|
453
512
|
allowResubmission: z.ZodDefault<z.ZodBoolean>;
|
|
513
|
+
rubric: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
514
|
+
id: z.ZodString;
|
|
515
|
+
title: z.ZodString;
|
|
516
|
+
description: z.ZodDefault<z.ZodString>;
|
|
517
|
+
maxPoints: z.ZodNumber;
|
|
518
|
+
}, z.core.$strip>>>;
|
|
454
519
|
}, z.core.$strip>>>;
|
|
455
520
|
}, z.core.$strip>>>;
|
|
456
521
|
}, z.core.$strip>>>;
|
|
@@ -486,12 +551,29 @@ declare const quizSubmitSchema: z.ZodObject<{
|
|
|
486
551
|
lessonId: z.ZodString;
|
|
487
552
|
attemptId: z.ZodString;
|
|
488
553
|
answers: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
554
|
+
expectedDraftRevision: z.ZodOptional<z.ZodNumber>;
|
|
555
|
+
}, z.core.$strip>;
|
|
556
|
+
declare const quizDraftSchema: z.ZodObject<{
|
|
557
|
+
courseId: z.ZodString;
|
|
558
|
+
lessonId: z.ZodString;
|
|
559
|
+
attemptId: z.ZodString;
|
|
560
|
+
answers: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
561
|
+
expectedDraftRevision: z.ZodDefault<z.ZodNumber>;
|
|
489
562
|
}, z.core.$strip>;
|
|
490
563
|
declare const assignmentSubmitSchema: z.ZodObject<{
|
|
491
564
|
courseId: z.ZodString;
|
|
492
565
|
lessonId: z.ZodString;
|
|
493
566
|
body: z.ZodString;
|
|
494
567
|
attachmentUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
568
|
+
submissionId: z.ZodOptional<z.ZodString>;
|
|
569
|
+
expectedDraftRevision: z.ZodOptional<z.ZodNumber>;
|
|
570
|
+
}, z.core.$strip>;
|
|
571
|
+
declare const assignmentDraftSchema: z.ZodObject<{
|
|
572
|
+
courseId: z.ZodString;
|
|
573
|
+
lessonId: z.ZodString;
|
|
574
|
+
body: z.ZodDefault<z.ZodString>;
|
|
575
|
+
attachmentUrl: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
576
|
+
expectedDraftRevision: z.ZodNumber;
|
|
495
577
|
}, z.core.$strip>;
|
|
496
578
|
declare const enrollmentRequestSchema: z.ZodObject<{
|
|
497
579
|
courseId: z.ZodString;
|
|
@@ -501,9 +583,9 @@ declare const enrollmentAdminSchema: z.ZodObject<{
|
|
|
501
583
|
courseId: z.ZodString;
|
|
502
584
|
userId: z.ZodString;
|
|
503
585
|
status: z.ZodEnum<{
|
|
586
|
+
suspended: "suspended";
|
|
504
587
|
active: "active";
|
|
505
588
|
rejected: "rejected";
|
|
506
|
-
suspended: "suspended";
|
|
507
589
|
cancelled: "cancelled";
|
|
508
590
|
}>;
|
|
509
591
|
reason: z.ZodDefault<z.ZodString>;
|
|
@@ -516,7 +598,12 @@ declare const gradeSchema: z.ZodObject<{
|
|
|
516
598
|
lessonId: z.ZodString;
|
|
517
599
|
userId: z.ZodString;
|
|
518
600
|
submissionId: z.ZodString;
|
|
519
|
-
points: z.ZodNumber
|
|
601
|
+
points: z.ZodOptional<z.ZodNumber>;
|
|
602
|
+
rubricScores: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
603
|
+
criterionId: z.ZodString;
|
|
604
|
+
points: z.ZodNumber;
|
|
605
|
+
feedback: z.ZodDefault<z.ZodString>;
|
|
606
|
+
}, z.core.$strip>>>;
|
|
520
607
|
feedback: z.ZodDefault<z.ZodString>;
|
|
521
608
|
}, z.core.$strip>;
|
|
522
609
|
declare const discussionSchema: z.ZodObject<{
|
|
@@ -578,7 +665,53 @@ declare const noteSchema: z.ZodObject<{
|
|
|
578
665
|
courseId: z.ZodString;
|
|
579
666
|
lessonId: z.ZodString;
|
|
580
667
|
note: z.ZodString;
|
|
668
|
+
expectedRevision: z.ZodDefault<z.ZodNumber>;
|
|
669
|
+
}, z.core.$strip>;
|
|
670
|
+
declare const studyNoteSchema: z.ZodObject<{
|
|
671
|
+
courseId: z.ZodString;
|
|
672
|
+
lessonId: z.ZodString;
|
|
673
|
+
id: z.ZodString;
|
|
674
|
+
body: z.ZodString;
|
|
675
|
+
positionSeconds: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
676
|
+
starred: z.ZodDefault<z.ZodBoolean>;
|
|
677
|
+
archived: z.ZodDefault<z.ZodBoolean>;
|
|
678
|
+
expectedRevision: z.ZodNumber;
|
|
679
|
+
}, z.core.$strip>;
|
|
680
|
+
declare const preferencesSchema: z.ZodObject<{
|
|
681
|
+
emailNotifications: z.ZodDefault<z.ZodBoolean>;
|
|
682
|
+
weeklyGoalLessons: z.ZodDefault<z.ZodNumber>;
|
|
683
|
+
}, z.core.$strip>;
|
|
684
|
+
declare const playbackSchema: z.ZodObject<{
|
|
685
|
+
courseId: z.ZodString;
|
|
686
|
+
lessonId: z.ZodString;
|
|
687
|
+
positionSeconds: z.ZodNumber;
|
|
688
|
+
playbackRate: z.ZodNumber;
|
|
689
|
+
expectedRevision: z.ZodNumber;
|
|
690
|
+
}, z.core.$strip>;
|
|
691
|
+
declare const pathDataSchema: z.ZodObject<{
|
|
692
|
+
title: z.ZodString;
|
|
693
|
+
description: z.ZodDefault<z.ZodString>;
|
|
694
|
+
courseIds: z.ZodArray<z.ZodString>;
|
|
695
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
696
|
+
draft: "draft";
|
|
697
|
+
published: "published";
|
|
698
|
+
archived: "archived";
|
|
699
|
+
}>>;
|
|
700
|
+
}, z.core.$strip>;
|
|
701
|
+
declare const pathSaveSchema: z.ZodObject<{
|
|
702
|
+
id: z.ZodOptional<z.ZodString>;
|
|
703
|
+
expectedRevision: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
704
|
+
data: z.ZodObject<{
|
|
705
|
+
title: z.ZodString;
|
|
706
|
+
description: z.ZodDefault<z.ZodString>;
|
|
707
|
+
courseIds: z.ZodArray<z.ZodString>;
|
|
708
|
+
status: z.ZodDefault<z.ZodEnum<{
|
|
709
|
+
draft: "draft";
|
|
710
|
+
published: "published";
|
|
711
|
+
archived: "archived";
|
|
712
|
+
}>>;
|
|
713
|
+
}, z.core.$strip>;
|
|
581
714
|
}, z.core.$strip>;
|
|
582
715
|
//#endregion
|
|
583
|
-
export { answersSchema, assignmentSchema, assignmentSubmitSchema, catalogSchema, certificateActionSchema, certificateRevokeSchema, cohortDataSchema, cohortSaveSchema, courseDataSchema, courseIdSchema, courseSaveSchema, discussionSchema, enrollmentAdminSchema, enrollmentRequestSchema, gradeSchema, idSchema, keySchema, lessonIdSchema, lessonSchema, moderateSchema, moduleSchema, noteSchema, pageSchema, questionSchema, quizSchema, quizSubmitSchema, resourceSchema, reviewSchema, safeUrlSchema, settingsSchema };
|
|
716
|
+
export { answersSchema, assignmentDraftSchema, assignmentSchema, assignmentSubmitSchema, catalogSchema, certificateActionSchema, certificateRevokeSchema, cohortDataSchema, cohortSaveSchema, courseDataSchema, courseIdSchema, courseSaveSchema, discussionSchema, enrollmentAdminSchema, enrollmentRequestSchema, gradeSchema, idSchema, keySchema, lessonIdSchema, lessonSchema, moderateSchema, moduleSchema, noteSchema, pageSchema, pathDataSchema, pathSaveSchema, playbackSchema, preferencesSchema, questionSchema, quizDraftSchema, quizSchema, quizSubmitSchema, resourceSchema, reviewSchema, rubricCriterionSchema, rubricScoreSchema, safeUrlSchema, settingsSchema, studyNoteSchema };
|
|
584
717
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.js
CHANGED
|
@@ -84,13 +84,35 @@ const quizSchema = z.object({
|
|
|
84
84
|
"never"
|
|
85
85
|
]).default("after_pass")
|
|
86
86
|
}).refine((quiz) => new Set(quiz.questions.map((question) => question.id)).size === quiz.questions.length, "Question IDs must be unique.");
|
|
87
|
+
const rubricCriterionSchema = z.object({
|
|
88
|
+
id: idSchema,
|
|
89
|
+
title,
|
|
90
|
+
description: z.string().max(2e3).default(""),
|
|
91
|
+
maxPoints: z.number().int().min(1).max(1e3)
|
|
92
|
+
});
|
|
93
|
+
const rubricScoreSchema = z.object({
|
|
94
|
+
criterionId: idSchema,
|
|
95
|
+
points: z.number().int().min(0).max(1e3),
|
|
96
|
+
feedback: z.string().max(2e3).default("")
|
|
97
|
+
});
|
|
87
98
|
const assignmentSchema = z.object({
|
|
88
99
|
instructions: z.string().trim().min(1).max(2e4),
|
|
89
100
|
maxPoints: z.number().int().min(1).max(1e3).default(100),
|
|
90
101
|
passingPoints: z.number().int().min(1).max(1e3).default(60),
|
|
91
102
|
dueAt: timestamp.nullable().default(null),
|
|
92
|
-
allowResubmission: z.boolean().default(true)
|
|
93
|
-
|
|
103
|
+
allowResubmission: z.boolean().default(true),
|
|
104
|
+
rubric: z.array(rubricCriterionSchema).max(20).optional()
|
|
105
|
+
}).refine((assignment) => assignment.passingPoints <= assignment.maxPoints, "Passing points cannot exceed maximum points.").superRefine((assignment, ctx) => {
|
|
106
|
+
const rubric = assignment.rubric ?? [];
|
|
107
|
+
if (new Set(rubric.map((item) => item.id)).size !== rubric.length) ctx.addIssue({
|
|
108
|
+
code: "custom",
|
|
109
|
+
message: "Rubric criterion IDs must be unique."
|
|
110
|
+
});
|
|
111
|
+
if (rubric.length && rubric.reduce((sum, item) => sum + item.maxPoints, 0) !== assignment.maxPoints) ctx.addIssue({
|
|
112
|
+
code: "custom",
|
|
113
|
+
message: "Rubric points must add up to the assignment maximum."
|
|
114
|
+
});
|
|
115
|
+
});
|
|
94
116
|
const lessonSchema = z.object({
|
|
95
117
|
id: idSchema,
|
|
96
118
|
title,
|
|
@@ -111,6 +133,12 @@ const lessonSchema = z.object({
|
|
|
111
133
|
field: idSchema.default("content")
|
|
112
134
|
}).nullable().default(null),
|
|
113
135
|
mediaUrl: safeUrlSchema.nullable().default(null),
|
|
136
|
+
transcript: text.default(""),
|
|
137
|
+
captions: z.array(z.object({
|
|
138
|
+
src: safeUrlSchema,
|
|
139
|
+
language: z.string().regex(/^[a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})*$/).max(35),
|
|
140
|
+
label: title
|
|
141
|
+
})).max(20).default([]),
|
|
114
142
|
liveStartsAt: timestamp.nullable().default(null),
|
|
115
143
|
durationMinutes: z.number().int().min(0).max(1440).default(10),
|
|
116
144
|
minStudySeconds: z.number().int().min(0).max(86400).default(0),
|
|
@@ -243,11 +271,20 @@ const lessonIdSchema = courseIdSchema.extend({ lessonId: idSchema });
|
|
|
243
271
|
const answersSchema = z.record(idSchema, z.union([z.string().max(2e3), z.array(z.string().max(500)).max(10)]));
|
|
244
272
|
const quizSubmitSchema = lessonIdSchema.extend({
|
|
245
273
|
attemptId: idSchema,
|
|
246
|
-
answers: answersSchema
|
|
274
|
+
answers: answersSchema,
|
|
275
|
+
expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional()
|
|
247
276
|
});
|
|
277
|
+
const quizDraftSchema = quizSubmitSchema.extend({ expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0) });
|
|
248
278
|
const assignmentSubmitSchema = lessonIdSchema.extend({
|
|
249
279
|
body: z.string().trim().min(1).max(2e4),
|
|
250
|
-
attachmentUrl: safeUrlSchema.nullable().default(null)
|
|
280
|
+
attachmentUrl: safeUrlSchema.nullable().default(null),
|
|
281
|
+
submissionId: idSchema.optional(),
|
|
282
|
+
expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER - 1).optional()
|
|
283
|
+
});
|
|
284
|
+
const assignmentDraftSchema = lessonIdSchema.extend({
|
|
285
|
+
body: z.string().max(2e4).default(""),
|
|
286
|
+
attachmentUrl: safeUrlSchema.nullable().default(null),
|
|
287
|
+
expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER - 1)
|
|
251
288
|
});
|
|
252
289
|
const enrollmentRequestSchema = courseIdSchema.extend({ cohortId: idSchema.optional() });
|
|
253
290
|
const enrollmentAdminSchema = courseIdSchema.extend({
|
|
@@ -266,7 +303,8 @@ const enrollmentAdminSchema = courseIdSchema.extend({
|
|
|
266
303
|
const gradeSchema = lessonIdSchema.extend({
|
|
267
304
|
userId: idSchema,
|
|
268
305
|
submissionId: idSchema,
|
|
269
|
-
points: z.number().int().min(0).max(1e3),
|
|
306
|
+
points: z.number().int().min(0).max(1e3).optional(),
|
|
307
|
+
rubricScores: z.array(rubricScoreSchema).max(20).optional(),
|
|
270
308
|
feedback: z.string().max(1e4).default("")
|
|
271
309
|
});
|
|
272
310
|
const discussionSchema = lessonIdSchema.extend({
|
|
@@ -308,8 +346,43 @@ const certificateRevokeSchema = courseIdSchema.extend({
|
|
|
308
346
|
userId: idSchema,
|
|
309
347
|
reason: z.string().trim().min(1).max(1e3)
|
|
310
348
|
});
|
|
311
|
-
const noteSchema = lessonIdSchema.extend({
|
|
349
|
+
const noteSchema = lessonIdSchema.extend({
|
|
350
|
+
note: z.string().max(1e4),
|
|
351
|
+
expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER - 1).default(0)
|
|
352
|
+
});
|
|
353
|
+
const studyNoteSchema = lessonIdSchema.extend({
|
|
354
|
+
id: idSchema,
|
|
355
|
+
body: z.string().max(5e3),
|
|
356
|
+
positionSeconds: z.number().min(0).max(86400).nullable().default(null),
|
|
357
|
+
starred: z.boolean().default(false),
|
|
358
|
+
archived: z.boolean().default(false),
|
|
359
|
+
expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER - 1)
|
|
360
|
+
}).refine((note) => note.body.trim().length > 0 || note.positionSeconds !== null, "Write a note or choose a media timestamp.");
|
|
361
|
+
const preferencesSchema = z.object({
|
|
362
|
+
emailNotifications: z.boolean().default(true),
|
|
363
|
+
weeklyGoalLessons: z.number().int().min(0).max(100).default(3)
|
|
364
|
+
});
|
|
365
|
+
const playbackSchema = lessonIdSchema.extend({
|
|
366
|
+
positionSeconds: z.number().finite().min(0).max(86400),
|
|
367
|
+
playbackRate: z.number().min(.25).max(3),
|
|
368
|
+
expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)
|
|
369
|
+
});
|
|
370
|
+
const pathDataSchema = z.object({
|
|
371
|
+
title,
|
|
372
|
+
description: z.string().max(5e3).default(""),
|
|
373
|
+
courseIds: z.array(idSchema).min(1).max(30).refine((ids) => new Set(ids).size === ids.length, "Courses must be unique."),
|
|
374
|
+
status: z.enum([
|
|
375
|
+
"draft",
|
|
376
|
+
"published",
|
|
377
|
+
"archived"
|
|
378
|
+
]).default("draft")
|
|
379
|
+
});
|
|
380
|
+
const pathSaveSchema = z.object({
|
|
381
|
+
id: idSchema.optional(),
|
|
382
|
+
expectedRevision: z.string().max(128).nullable().default(null),
|
|
383
|
+
data: pathDataSchema
|
|
384
|
+
});
|
|
312
385
|
|
|
313
386
|
//#endregion
|
|
314
|
-
export { answersSchema, assignmentSchema, assignmentSubmitSchema, catalogSchema, certificateActionSchema, certificateRevokeSchema, cohortDataSchema, cohortSaveSchema, courseDataSchema, courseIdSchema, courseSaveSchema, discussionSchema, enrollmentAdminSchema, enrollmentRequestSchema, gradeSchema, idSchema, keySchema, lessonIdSchema, lessonSchema, moderateSchema, moduleSchema, noteSchema, pageSchema, questionSchema, quizSchema, quizSubmitSchema, resourceSchema, reviewSchema, safeUrlSchema, settingsSchema };
|
|
387
|
+
export { answersSchema, assignmentDraftSchema, assignmentSchema, assignmentSubmitSchema, catalogSchema, certificateActionSchema, certificateRevokeSchema, cohortDataSchema, cohortSaveSchema, courseDataSchema, courseIdSchema, courseSaveSchema, discussionSchema, enrollmentAdminSchema, enrollmentRequestSchema, gradeSchema, idSchema, keySchema, lessonIdSchema, lessonSchema, moderateSchema, moduleSchema, noteSchema, pageSchema, pathDataSchema, pathSaveSchema, playbackSchema, preferencesSchema, questionSchema, quizDraftSchema, quizSchema, quizSubmitSchema, resourceSchema, reviewSchema, rubricCriterionSchema, rubricScoreSchema, safeUrlSchema, settingsSchema, studyNoteSchema };
|
|
315
388
|
//# sourceMappingURL=schemas.js.map
|
package/dist/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const idSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9_-]+$/, \"Use letters, numbers, underscores or hyphens.\")\n .refine(\n (value) => ![\"__proto__\", \"constructor\", \"prototype\"].includes(value),\n \"This identifier is reserved. Choose another ID.\",\n );\nexport const keySchema = z\n .string()\n .min(1)\n .max(1024)\n .regex(/^[a-zA-Z0-9_:.-]+$/);\nconst title = z.string().trim().min(1).max(200);\nconst text = z.string().max(50_000);\nconst timestamp = z.iso.datetime({ offset: true });\nexport const safeUrlSchema = z\n .string()\n .max(2048)\n .refine((value) => {\n if (/^\\/(?!\\/)[^\\s\\\\]*$/.test(value)) return true;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" && !url.username && !url.password;\n } catch {\n return false;\n }\n }, \"Use an HTTPS URL or a path on this site.\");\n\nexport const resourceSchema = z.object({\n id: idSchema,\n title,\n url: safeUrlSchema,\n description: z.string().max(1000).default(\"\"),\n});\nconst optionSchema = z.object({ id: idSchema, text: z.string().trim().min(1).max(2000) });\nexport const questionSchema = z\n .object({\n id: idSchema,\n type: z.enum([\"single\", \"multiple\", \"true_false\", \"short\"]),\n prompt: z.string().trim().min(1).max(5000),\n options: z.array(optionSchema).max(10).default([]),\n correctAnswers: z.array(z.string().trim().min(1).max(500)).min(1).max(10),\n points: z.number().int().min(1).max(100).default(1),\n explanation: z.string().max(5000).default(\"\"),\n })\n .superRefine((question, ctx) => {\n const optionIds = question.options.map((option) => option.id);\n if (new Set(optionIds).size !== optionIds.length)\n ctx.addIssue({ code: \"custom\", message: \"Option IDs must be unique.\" });\n if (new Set(question.correctAnswers).size !== question.correctAnswers.length)\n ctx.addIssue({ code: \"custom\", message: \"Correct answers must be unique.\" });\n if (question.type !== \"short\") {\n if (question.options.length < 2)\n ctx.addIssue({ code: \"custom\", message: \"Choice questions need at least two options.\" });\n if (question.correctAnswers.some((answer) => !optionIds.includes(answer)))\n ctx.addIssue({ code: \"custom\", message: \"Correct answers must refer to option IDs.\" });\n if (question.type !== \"multiple\" && question.correctAnswers.length !== 1)\n ctx.addIssue({ code: \"custom\", message: \"This question requires one correct answer.\" });\n if (\n question.type === \"true_false\" &&\n (question.options.length !== 2 ||\n !optionIds.includes(\"true\") ||\n !optionIds.includes(\"false\"))\n )\n ctx.addIssue({\n code: \"custom\",\n message: \"True/false options must have the IDs true and false.\",\n });\n }\n });\nexport const quizSchema = z\n .object({\n questions: z.array(questionSchema).min(1).max(50),\n passingPercent: z.number().int().min(1).max(100).default(70),\n maxAttempts: z.number().int().min(1).max(20).default(3),\n timeLimitMinutes: z.number().int().min(0).max(180).default(30),\n randomizeQuestions: z.boolean().default(true),\n randomizeOptions: z.boolean().default(false),\n showFeedback: z.enum([\"after_pass\", \"after_submit\", \"never\"]).default(\"after_pass\"),\n })\n .refine(\n (quiz) => new Set(quiz.questions.map((question) => question.id)).size === quiz.questions.length,\n \"Question IDs must be unique.\",\n );\n\nexport const assignmentSchema = z\n .object({\n instructions: z.string().trim().min(1).max(20_000),\n maxPoints: z.number().int().min(1).max(1000).default(100),\n passingPoints: z.number().int().min(1).max(1000).default(60),\n dueAt: timestamp.nullable().default(null),\n allowResubmission: z.boolean().default(true),\n })\n .refine(\n (assignment) => assignment.passingPoints <= assignment.maxPoints,\n \"Passing points cannot exceed maximum points.\",\n );\n\nexport const lessonSchema = z\n .object({\n id: idSchema,\n title,\n summary: z.string().max(2000).default(\"\"),\n kind: z.enum([\"text\", \"video\", \"audio\", \"quiz\", \"assignment\", \"live\"]).default(\"text\"),\n body: text.default(\"\"),\n portableText: z.array(z.record(z.string(), z.unknown())).max(1000).default([]),\n contentSource: z\n .object({ collection: idSchema, id: idSchema, field: idSchema.default(\"content\") })\n .nullable()\n .default(null),\n mediaUrl: safeUrlSchema.nullable().default(null),\n liveStartsAt: timestamp.nullable().default(null),\n durationMinutes: z.number().int().min(0).max(1440).default(10),\n minStudySeconds: z.number().int().min(0).max(86400).default(0),\n preview: z.boolean().default(false),\n required: z.boolean().default(true),\n resources: z.array(resourceSchema).max(30).default([]),\n quiz: quizSchema.nullable().default(null),\n assignment: assignmentSchema.nullable().default(null),\n })\n .superRefine((lesson, ctx) => {\n if (lesson.kind === \"quiz\" && !lesson.quiz)\n ctx.addIssue({ code: \"custom\", message: \"Quiz lessons need a quiz.\" });\n if (lesson.kind === \"assignment\" && !lesson.assignment)\n ctx.addIssue({ code: \"custom\", message: \"Assignment lessons need an assignment.\" });\n if ([\"video\", \"audio\", \"live\"].includes(lesson.kind) && !lesson.mediaUrl)\n ctx.addIssue({ code: \"custom\", message: \"Media and live lessons need a URL.\" });\n if (lesson.kind === \"live\" && !lesson.liveStartsAt)\n ctx.addIssue({ code: \"custom\", message: \"Live lessons need a start time.\" });\n if (new Set(lesson.resources.map((resource) => resource.id)).size !== lesson.resources.length)\n ctx.addIssue({ code: \"custom\", message: \"Resource IDs must be unique.\" });\n });\n\nexport const moduleSchema = z.object({\n id: idSchema,\n title,\n description: z.string().max(2000).default(\"\"),\n releaseDays: z.number().int().min(0).max(3650).default(0),\n unlockAt: timestamp.nullable().default(null),\n lessons: z.array(lessonSchema).max(100).default([]),\n});\n\nexport const courseDataSchema = z\n .object({\n slug: z\n .string()\n .trim()\n .min(1)\n .max(100)\n .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, \"Use lowercase words separated by hyphens.\"),\n title,\n summary: z.string().trim().max(1000).default(\"\"),\n description: text.default(\"\"),\n outcomes: z.array(z.string().trim().min(1).max(500)).max(30).default([]),\n requirements: z.array(z.string().trim().min(1).max(500)).max(30).default([]),\n category: z.string().trim().max(100).default(\"\"),\n tags: z.array(z.string().trim().min(1).max(60)).max(20).default([]),\n language: z.string().trim().min(2).max(35).default(\"en\"),\n level: z.enum([\"beginner\", \"intermediate\", \"advanced\", \"all\"]).default(\"all\"),\n featuredImage: z\n .object({\n id: z.string().max(128).default(\"\"),\n src: safeUrlSchema,\n alt: z.string().max(500).default(\"\"),\n })\n .nullable()\n .default(null),\n instructorName: z.string().trim().max(200).default(\"\"),\n instructorIds: z.array(idSchema).max(20).default([]),\n status: z.enum([\"draft\", \"published\", \"archived\"]).default(\"draft\"),\n enrollmentMode: z.enum([\"open\", \"approval\", \"invite\"]).default(\"open\"),\n commerce: z\n .object({\n accessModel: z.enum([\"free\", \"paid\"]).default(\"free\"),\n offerId: idSchema.nullable().default(null),\n priceMinor: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).nullable().default(null),\n currency: z\n .string()\n .regex(/^[A-Z]{3}$/)\n .default(\"INR\"),\n })\n .default({ accessModel: \"free\", offerId: null, priceMinor: null, currency: \"INR\" }),\n prerequisiteCourseIds: z.array(idSchema).max(20).default([]),\n sequential: z.boolean().default(true),\n enrollmentClosesAt: timestamp.nullable().default(null),\n accessDays: z.number().int().min(0).max(3650).default(0),\n certificateEnabled: z.boolean().default(true),\n modules: z.array(moduleSchema).max(50).default([]),\n })\n .superRefine((course, ctx) => {\n const allIds = course.modules.flatMap((module) => [\n module.id,\n ...module.lessons.map((lesson) => lesson.id),\n ]);\n if (new Set(allIds).size !== allIds.length)\n ctx.addIssue({\n code: \"custom\",\n message: \"Module and lesson IDs must be unique across the course.\",\n });\n if (course.modules.flatMap((module) => module.lessons).length > 150)\n ctx.addIssue({ code: \"custom\", message: \"A course supports up to 150 lessons.\" });\n if (\n course.status === \"published\" &&\n !course.modules.some((module) => module.lessons.some((lesson) => lesson.required))\n )\n ctx.addIssue({\n code: \"custom\",\n message: \"Publish a course with at least one required lesson.\",\n });\n });\n\nexport const courseSaveSchema = z.object({\n id: idSchema.optional(),\n expectedRevision: z.string().max(128).nullable().default(null),\n data: courseDataSchema,\n});\nexport const pageSchema = z.object({\n cursor: z.string().max(4000).optional(),\n limit: z.coerce.number().int().min(1).max(100).default(24),\n});\nexport const catalogSchema = pageSchema.extend({\n q: z.string().max(100).default(\"\"),\n category: z.string().max(100).default(\"\"),\n level: z.enum([\"beginner\", \"intermediate\", \"advanced\", \"all\"]).optional(),\n language: z.string().max(35).optional(),\n});\nexport const courseIdSchema = z.object({ courseId: idSchema });\nexport const lessonIdSchema = courseIdSchema.extend({ lessonId: idSchema });\nexport const answersSchema = z.record(\n idSchema,\n z.union([z.string().max(2000), z.array(z.string().max(500)).max(10)]),\n);\nexport const quizSubmitSchema = lessonIdSchema.extend({\n attemptId: idSchema,\n answers: answersSchema,\n});\nexport const assignmentSubmitSchema = lessonIdSchema.extend({\n body: z.string().trim().min(1).max(20_000),\n attachmentUrl: safeUrlSchema.nullable().default(null),\n});\nexport const enrollmentRequestSchema = courseIdSchema.extend({ cohortId: idSchema.optional() });\nexport const enrollmentAdminSchema = courseIdSchema.extend({\n userId: idSchema,\n status: z.enum([\"active\", \"rejected\", \"suspended\", \"cancelled\"]),\n reason: z.string().max(1000).default(\"\"),\n cohortId: idSchema.nullable().optional(),\n accessStartsAt: timestamp.nullable().optional(),\n accessExpiresAt: timestamp.nullable().optional(),\n});\nexport const gradeSchema = lessonIdSchema.extend({\n userId: idSchema,\n submissionId: idSchema,\n points: z.number().int().min(0).max(1000),\n feedback: z.string().max(10_000).default(\"\"),\n});\nexport const discussionSchema = lessonIdSchema.extend({\n body: z.string().trim().min(1).max(5000),\n parentId: idSchema.nullable().default(null),\n});\nexport const reviewSchema = courseIdSchema.extend({\n rating: z.number().int().min(1).max(5),\n body: z.string().trim().min(1).max(3000),\n});\nexport const moderateSchema = z.object({\n id: keySchema,\n status: z.enum([\"published\", \"hidden\"]),\n expectedRevision: z.string().min(1).max(128),\n});\nexport const cohortDataSchema = z\n .object({\n title,\n courseIds: z.array(idSchema).min(1).max(20),\n memberIds: z.array(idSchema).max(1000).default([]),\n startsAt: timestamp.nullable().default(null),\n endsAt: timestamp.nullable().default(null),\n })\n .refine(\n (cohort) =>\n !cohort.startsAt || !cohort.endsAt || Date.parse(cohort.endsAt) > Date.parse(cohort.startsAt),\n \"Cohort end must follow its start.\",\n )\n .refine(\n (cohort) => new Set(cohort.memberIds).size === cohort.memberIds.length,\n \"Cohort members must be unique.\",\n )\n .refine(\n (cohort) => new Set(cohort.courseIds).size === cohort.courseIds.length,\n \"Cohort courses must be unique.\",\n );\nexport const cohortSaveSchema = z.object({\n id: idSchema.optional(),\n expectedRevision: z.string().max(128).nullable().default(null),\n data: cohortDataSchema,\n});\nexport const settingsSchema = z.object({\n academyTitle: title.default(\"Ananta Gnanam Academy\"),\n academyDescription: z.string().max(2000).default(\"Build knowledge, one lesson at a time.\"),\n issuerName: title.default(\"Ananta Gnanam\"),\n moderateDiscussions: z.boolean().default(true),\n moderateReviews: z.boolean().default(true),\n emailNotifications: z.boolean().default(false),\n reminderDays: z.number().int().min(0).max(90).default(7),\n});\nexport const certificateActionSchema = courseIdSchema.extend({ shared: z.boolean() });\nexport const certificateRevokeSchema = courseIdSchema.extend({\n userId: idSchema,\n reason: z.string().trim().min(1).max(1000),\n});\nexport const noteSchema = lessonIdSchema.extend({ note: z.string().max(10_000) });\n"],"mappings":";;;AAEA,MAAa,WAAW,EACrB,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,IAAI,CACR,MAAM,oBAAoB,gDAAgD,CAC1E,QACE,UAAU,CAAC;CAAC;CAAa;CAAe;CAAY,CAAC,SAAS,MAAM,EACrE,kDACD;AACH,MAAa,YAAY,EACtB,QAAQ,CACR,IAAI,EAAE,CACN,IAAI,KAAK,CACT,MAAM,qBAAqB;AAC9B,MAAM,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;AAC/C,MAAM,OAAO,EAAE,QAAQ,CAAC,IAAI,IAAO;AACnC,MAAM,YAAY,EAAE,IAAI,SAAS,EAAE,QAAQ,MAAM,CAAC;AAClD,MAAa,gBAAgB,EAC1B,QAAQ,CACR,IAAI,KAAK,CACT,QAAQ,UAAU;AACjB,KAAI,qBAAqB,KAAK,MAAM,CAAE,QAAO;AAC7C,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,MAAM;AAC1B,SAAO,IAAI,aAAa,YAAY,CAAC,IAAI,YAAY,CAAC,IAAI;SACpD;AACN,SAAO;;GAER,2CAA2C;AAEhD,MAAa,iBAAiB,EAAE,OAAO;CACrC,IAAI;CACJ;CACA,KAAK;CACL,aAAa,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CAC9C,CAAC;AACF,MAAM,eAAe,EAAE,OAAO;CAAE,IAAI;CAAU,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CAAE,CAAC;AACzF,MAAa,iBAAiB,EAC3B,OAAO;CACN,IAAI;CACJ,MAAM,EAAE,KAAK;EAAC;EAAU;EAAY;EAAc;EAAQ,CAAC;CAC3D,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CAC1C,SAAS,EAAE,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CAClD,gBAAgB,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG;CACzE,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;CACnD,aAAa,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CAC9C,CAAC,CACD,aAAa,UAAU,QAAQ;CAC9B,MAAM,YAAY,SAAS,QAAQ,KAAK,WAAW,OAAO,GAAG;AAC7D,KAAI,IAAI,IAAI,UAAU,CAAC,SAAS,UAAU,OACxC,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAA8B,CAAC;AACzE,KAAI,IAAI,IAAI,SAAS,eAAe,CAAC,SAAS,SAAS,eAAe,OACpE,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAAmC,CAAC;AAC9E,KAAI,SAAS,SAAS,SAAS;AAC7B,MAAI,SAAS,QAAQ,SAAS,EAC5B,KAAI,SAAS;GAAE,MAAM;GAAU,SAAS;GAA+C,CAAC;AAC1F,MAAI,SAAS,eAAe,MAAM,WAAW,CAAC,UAAU,SAAS,OAAO,CAAC,CACvE,KAAI,SAAS;GAAE,MAAM;GAAU,SAAS;GAA6C,CAAC;AACxF,MAAI,SAAS,SAAS,cAAc,SAAS,eAAe,WAAW,EACrE,KAAI,SAAS;GAAE,MAAM;GAAU,SAAS;GAA8C,CAAC;AACzF,MACE,SAAS,SAAS,iBACjB,SAAS,QAAQ,WAAW,KAC3B,CAAC,UAAU,SAAS,OAAO,IAC3B,CAAC,UAAU,SAAS,QAAQ,EAE9B,KAAI,SAAS;GACX,MAAM;GACN,SAAS;GACV,CAAC;;EAEN;AACJ,MAAa,aAAa,EACvB,OAAO;CACN,WAAW,EAAE,MAAM,eAAe,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG;CACjD,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CAC5D,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE;CACvD,kBAAkB,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CAC9D,oBAAoB,EAAE,SAAS,CAAC,QAAQ,KAAK;CAC7C,kBAAkB,EAAE,SAAS,CAAC,QAAQ,MAAM;CAC5C,cAAc,EAAE,KAAK;EAAC;EAAc;EAAgB;EAAQ,CAAC,CAAC,QAAQ,aAAa;CACpF,CAAC,CACD,QACE,SAAS,IAAI,IAAI,KAAK,UAAU,KAAK,aAAa,SAAS,GAAG,CAAC,CAAC,SAAS,KAAK,UAAU,QACzF,+BACD;AAEH,MAAa,mBAAmB,EAC7B,OAAO;CACN,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAO;CAClD,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK,CAAC,QAAQ,IAAI;CACzD,eAAe,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CAC5D,OAAO,UAAU,UAAU,CAAC,QAAQ,KAAK;CACzC,mBAAmB,EAAE,SAAS,CAAC,QAAQ,KAAK;CAC7C,CAAC,CACD,QACE,eAAe,WAAW,iBAAiB,WAAW,WACvD,+CACD;AAEH,MAAa,eAAe,EACzB,OAAO;CACN,IAAI;CACJ;CACA,SAAS,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CACzC,MAAM,EAAE,KAAK;EAAC;EAAQ;EAAS;EAAS;EAAQ;EAAc;EAAO,CAAC,CAAC,QAAQ,OAAO;CACtF,MAAM,KAAK,QAAQ,GAAG;CACtB,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,IAAK,CAAC,QAAQ,EAAE,CAAC;CAC9E,eAAe,EACZ,OAAO;EAAE,YAAY;EAAU,IAAI;EAAU,OAAO,SAAS,QAAQ,UAAU;EAAE,CAAC,CAClF,UAAU,CACV,QAAQ,KAAK;CAChB,UAAU,cAAc,UAAU,CAAC,QAAQ,KAAK;CAChD,cAAc,UAAU,UAAU,CAAC,QAAQ,KAAK;CAChD,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,GAAG;CAC9D,iBAAiB,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE;CAC9D,SAAS,EAAE,SAAS,CAAC,QAAQ,MAAM;CACnC,UAAU,EAAE,SAAS,CAAC,QAAQ,KAAK;CACnC,WAAW,EAAE,MAAM,eAAe,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CACtD,MAAM,WAAW,UAAU,CAAC,QAAQ,KAAK;CACzC,YAAY,iBAAiB,UAAU,CAAC,QAAQ,KAAK;CACtD,CAAC,CACD,aAAa,QAAQ,QAAQ;AAC5B,KAAI,OAAO,SAAS,UAAU,CAAC,OAAO,KACpC,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAA6B,CAAC;AACxE,KAAI,OAAO,SAAS,gBAAgB,CAAC,OAAO,WAC1C,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAA0C,CAAC;AACrF,KAAI;EAAC;EAAS;EAAS;EAAO,CAAC,SAAS,OAAO,KAAK,IAAI,CAAC,OAAO,SAC9D,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAAsC,CAAC;AACjF,KAAI,OAAO,SAAS,UAAU,CAAC,OAAO,aACpC,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAAmC,CAAC;AAC9E,KAAI,IAAI,IAAI,OAAO,UAAU,KAAK,aAAa,SAAS,GAAG,CAAC,CAAC,SAAS,OAAO,UAAU,OACrF,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAAgC,CAAC;EAC3E;AAEJ,MAAa,eAAe,EAAE,OAAO;CACnC,IAAI;CACJ;CACA,aAAa,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CAC7C,aAAa,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE;CACzD,UAAU,UAAU,UAAU,CAAC,QAAQ,KAAK;CAC5C,SAAS,EAAE,MAAM,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;CACpD,CAAC;AAEF,MAAa,mBAAmB,EAC7B,OAAO;CACN,MAAM,EACH,QAAQ,CACR,MAAM,CACN,IAAI,EAAE,CACN,IAAI,IAAI,CACR,MAAM,8BAA8B,4CAA4C;CACnF;CACA,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CAChD,aAAa,KAAK,QAAQ,GAAG;CAC7B,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CACxE,cAAc,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CAC5E,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CAChD,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CACnE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,KAAK;CACxD,OAAO,EAAE,KAAK;EAAC;EAAY;EAAgB;EAAY;EAAM,CAAC,CAAC,QAAQ,MAAM;CAC7E,eAAe,EACZ,OAAO;EACN,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;EACnC,KAAK;EACL,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;EACrC,CAAC,CACD,UAAU,CACV,QAAQ,KAAK;CAChB,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CACtD,eAAe,EAAE,MAAM,SAAS,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CACpD,QAAQ,EAAE,KAAK;EAAC;EAAS;EAAa;EAAW,CAAC,CAAC,QAAQ,QAAQ;CACnE,gBAAgB,EAAE,KAAK;EAAC;EAAQ;EAAY;EAAS,CAAC,CAAC,QAAQ,OAAO;CACtE,UAAU,EACP,OAAO;EACN,aAAa,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,CAAC,QAAQ,OAAO;EACrD,SAAS,SAAS,UAAU,CAAC,QAAQ,KAAK;EAC1C,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,OAAO,iBAAiB,CAAC,UAAU,CAAC,QAAQ,KAAK;EACzF,UAAU,EACP,QAAQ,CACR,MAAM,aAAa,CACnB,QAAQ,MAAM;EAClB,CAAC,CACD,QAAQ;EAAE,aAAa;EAAQ,SAAS;EAAM,YAAY;EAAM,UAAU;EAAO,CAAC;CACrF,uBAAuB,EAAE,MAAM,SAAS,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CAC5D,YAAY,EAAE,SAAS,CAAC,QAAQ,KAAK;CACrC,oBAAoB,UAAU,UAAU,CAAC,QAAQ,KAAK;CACtD,YAAY,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE;CACxD,oBAAoB,EAAE,SAAS,CAAC,QAAQ,KAAK;CAC7C,SAAS,EAAE,MAAM,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;CACnD,CAAC,CACD,aAAa,QAAQ,QAAQ;CAC5B,MAAM,SAAS,OAAO,QAAQ,SAAS,WAAW,CAChD,OAAO,IACP,GAAG,OAAO,QAAQ,KAAK,WAAW,OAAO,GAAG,CAC7C,CAAC;AACF,KAAI,IAAI,IAAI,OAAO,CAAC,SAAS,OAAO,OAClC,KAAI,SAAS;EACX,MAAM;EACN,SAAS;EACV,CAAC;AACJ,KAAI,OAAO,QAAQ,SAAS,WAAW,OAAO,QAAQ,CAAC,SAAS,IAC9D,KAAI,SAAS;EAAE,MAAM;EAAU,SAAS;EAAwC,CAAC;AACnF,KACE,OAAO,WAAW,eAClB,CAAC,OAAO,QAAQ,MAAM,WAAW,OAAO,QAAQ,MAAM,WAAW,OAAO,SAAS,CAAC,CAElF,KAAI,SAAS;EACX,MAAM;EACN,SAAS;EACV,CAAC;EACJ;AAEJ,MAAa,mBAAmB,EAAE,OAAO;CACvC,IAAI,SAAS,UAAU;CACvB,kBAAkB,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK;CAC9D,MAAM;CACP,CAAC;AACF,MAAa,aAAa,EAAE,OAAO;CACjC,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,UAAU;CACvC,OAAO,EAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CAC3D,CAAC;AACF,MAAa,gBAAgB,WAAW,OAAO;CAC7C,GAAG,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CAClC,UAAU,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,GAAG;CACzC,OAAO,EAAE,KAAK;EAAC;EAAY;EAAgB;EAAY;EAAM,CAAC,CAAC,UAAU;CACzE,UAAU,EAAE,QAAQ,CAAC,IAAI,GAAG,CAAC,UAAU;CACxC,CAAC;AACF,MAAa,iBAAiB,EAAE,OAAO,EAAE,UAAU,UAAU,CAAC;AAC9D,MAAa,iBAAiB,eAAe,OAAO,EAAE,UAAU,UAAU,CAAC;AAC3E,MAAa,gBAAgB,EAAE,OAC7B,UACA,EAAE,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,IAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CACtE;AACD,MAAa,mBAAmB,eAAe,OAAO;CACpD,WAAW;CACX,SAAS;CACV,CAAC;AACF,MAAa,yBAAyB,eAAe,OAAO;CAC1D,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAO;CAC1C,eAAe,cAAc,UAAU,CAAC,QAAQ,KAAK;CACtD,CAAC;AACF,MAAa,0BAA0B,eAAe,OAAO,EAAE,UAAU,SAAS,UAAU,EAAE,CAAC;AAC/F,MAAa,wBAAwB,eAAe,OAAO;CACzD,QAAQ;CACR,QAAQ,EAAE,KAAK;EAAC;EAAU;EAAY;EAAa;EAAY,CAAC;CAChE,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,GAAG;CACxC,UAAU,SAAS,UAAU,CAAC,UAAU;CACxC,gBAAgB,UAAU,UAAU,CAAC,UAAU;CAC/C,iBAAiB,UAAU,UAAU,CAAC,UAAU;CACjD,CAAC;AACF,MAAa,cAAc,eAAe,OAAO;CAC/C,QAAQ;CACR,cAAc;CACd,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CACzC,UAAU,EAAE,QAAQ,CAAC,IAAI,IAAO,CAAC,QAAQ,GAAG;CAC7C,CAAC;AACF,MAAa,mBAAmB,eAAe,OAAO;CACpD,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CACxC,UAAU,SAAS,UAAU,CAAC,QAAQ,KAAK;CAC5C,CAAC;AACF,MAAa,eAAe,eAAe,OAAO;CAChD,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE;CACtC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CACzC,CAAC;AACF,MAAa,iBAAiB,EAAE,OAAO;CACrC,IAAI;CACJ,QAAQ,EAAE,KAAK,CAAC,aAAa,SAAS,CAAC;CACvC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI;CAC7C,CAAC;AACF,MAAa,mBAAmB,EAC7B,OAAO;CACN;CACA,WAAW,EAAE,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG;CAC3C,WAAW,EAAE,MAAM,SAAS,CAAC,IAAI,IAAK,CAAC,QAAQ,EAAE,CAAC;CAClD,UAAU,UAAU,UAAU,CAAC,QAAQ,KAAK;CAC5C,QAAQ,UAAU,UAAU,CAAC,QAAQ,KAAK;CAC3C,CAAC,CACD,QACE,WACC,CAAC,OAAO,YAAY,CAAC,OAAO,UAAU,KAAK,MAAM,OAAO,OAAO,GAAG,KAAK,MAAM,OAAO,SAAS,EAC/F,oCACD,CACA,QACE,WAAW,IAAI,IAAI,OAAO,UAAU,CAAC,SAAS,OAAO,UAAU,QAChE,iCACD,CACA,QACE,WAAW,IAAI,IAAI,OAAO,UAAU,CAAC,SAAS,OAAO,UAAU,QAChE,iCACD;AACH,MAAa,mBAAmB,EAAE,OAAO;CACvC,IAAI,SAAS,UAAU;CACvB,kBAAkB,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK;CAC9D,MAAM;CACP,CAAC;AACF,MAAa,iBAAiB,EAAE,OAAO;CACrC,cAAc,MAAM,QAAQ,wBAAwB;CACpD,oBAAoB,EAAE,QAAQ,CAAC,IAAI,IAAK,CAAC,QAAQ,yCAAyC;CAC1F,YAAY,MAAM,QAAQ,gBAAgB;CAC1C,qBAAqB,EAAE,SAAS,CAAC,QAAQ,KAAK;CAC9C,iBAAiB,EAAE,SAAS,CAAC,QAAQ,KAAK;CAC1C,oBAAoB,EAAE,SAAS,CAAC,QAAQ,MAAM;CAC9C,cAAc,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE;CACzD,CAAC;AACF,MAAa,0BAA0B,eAAe,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;AACrF,MAAa,0BAA0B,eAAe,OAAO;CAC3D,QAAQ;CACR,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,IAAK;CAC3C,CAAC;AACF,MAAa,aAAa,eAAe,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,IAAO,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"schemas.js","names":[],"sources":["../src/schemas.ts"],"sourcesContent":["import { z } from \"zod\";\n\nexport const idSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9_-]+$/, \"Use letters, numbers, underscores or hyphens.\")\n .refine(\n (value) => ![\"__proto__\", \"constructor\", \"prototype\"].includes(value),\n \"This identifier is reserved. Choose another ID.\",\n );\nexport const keySchema = z\n .string()\n .min(1)\n .max(1024)\n .regex(/^[a-zA-Z0-9_:.-]+$/);\nconst title = z.string().trim().min(1).max(200);\nconst text = z.string().max(50_000);\nconst timestamp = z.iso.datetime({ offset: true });\nexport const safeUrlSchema = z\n .string()\n .max(2048)\n .refine((value) => {\n if (/^\\/(?!\\/)[^\\s\\\\]*$/.test(value)) return true;\n try {\n const url = new URL(value);\n return url.protocol === \"https:\" && !url.username && !url.password;\n } catch {\n return false;\n }\n }, \"Use an HTTPS URL or a path on this site.\");\n\nexport const resourceSchema = z.object({\n id: idSchema,\n title,\n url: safeUrlSchema,\n description: z.string().max(1000).default(\"\"),\n});\nconst optionSchema = z.object({ id: idSchema, text: z.string().trim().min(1).max(2000) });\nexport const questionSchema = z\n .object({\n id: idSchema,\n type: z.enum([\"single\", \"multiple\", \"true_false\", \"short\"]),\n prompt: z.string().trim().min(1).max(5000),\n options: z.array(optionSchema).max(10).default([]),\n correctAnswers: z.array(z.string().trim().min(1).max(500)).min(1).max(10),\n points: z.number().int().min(1).max(100).default(1),\n explanation: z.string().max(5000).default(\"\"),\n })\n .superRefine((question, ctx) => {\n const optionIds = question.options.map((option) => option.id);\n if (new Set(optionIds).size !== optionIds.length)\n ctx.addIssue({ code: \"custom\", message: \"Option IDs must be unique.\" });\n if (new Set(question.correctAnswers).size !== question.correctAnswers.length)\n ctx.addIssue({ code: \"custom\", message: \"Correct answers must be unique.\" });\n if (question.type !== \"short\") {\n if (question.options.length < 2)\n ctx.addIssue({ code: \"custom\", message: \"Choice questions need at least two options.\" });\n if (question.correctAnswers.some((answer) => !optionIds.includes(answer)))\n ctx.addIssue({ code: \"custom\", message: \"Correct answers must refer to option IDs.\" });\n if (question.type !== \"multiple\" && question.correctAnswers.length !== 1)\n ctx.addIssue({ code: \"custom\", message: \"This question requires one correct answer.\" });\n if (\n question.type === \"true_false\" &&\n (question.options.length !== 2 ||\n !optionIds.includes(\"true\") ||\n !optionIds.includes(\"false\"))\n )\n ctx.addIssue({\n code: \"custom\",\n message: \"True/false options must have the IDs true and false.\",\n });\n }\n });\nexport const quizSchema = z\n .object({\n questions: z.array(questionSchema).min(1).max(50),\n passingPercent: z.number().int().min(1).max(100).default(70),\n maxAttempts: z.number().int().min(1).max(20).default(3),\n timeLimitMinutes: z.number().int().min(0).max(180).default(30),\n randomizeQuestions: z.boolean().default(true),\n randomizeOptions: z.boolean().default(false),\n showFeedback: z.enum([\"after_pass\", \"after_submit\", \"never\"]).default(\"after_pass\"),\n })\n .refine(\n (quiz) => new Set(quiz.questions.map((question) => question.id)).size === quiz.questions.length,\n \"Question IDs must be unique.\",\n );\n\nexport const rubricCriterionSchema = z.object({\n id: idSchema,\n title,\n description: z.string().max(2000).default(\"\"),\n maxPoints: z.number().int().min(1).max(1000),\n});\nexport const rubricScoreSchema = z.object({\n criterionId: idSchema,\n points: z.number().int().min(0).max(1000),\n feedback: z.string().max(2000).default(\"\"),\n});\nexport const assignmentSchema = z\n .object({\n instructions: z.string().trim().min(1).max(20_000),\n maxPoints: z.number().int().min(1).max(1000).default(100),\n passingPoints: z.number().int().min(1).max(1000).default(60),\n dueAt: timestamp.nullable().default(null),\n allowResubmission: z.boolean().default(true),\n rubric: z.array(rubricCriterionSchema).max(20).optional(),\n })\n .refine(\n (assignment) => assignment.passingPoints <= assignment.maxPoints,\n \"Passing points cannot exceed maximum points.\",\n )\n .superRefine((assignment, ctx) => {\n const rubric = assignment.rubric ?? [];\n if (new Set(rubric.map((item) => item.id)).size !== rubric.length)\n ctx.addIssue({ code: \"custom\", message: \"Rubric criterion IDs must be unique.\" });\n if (\n rubric.length &&\n rubric.reduce((sum, item) => sum + item.maxPoints, 0) !== assignment.maxPoints\n )\n ctx.addIssue({\n code: \"custom\",\n message: \"Rubric points must add up to the assignment maximum.\",\n });\n });\n\nexport const lessonSchema = z\n .object({\n id: idSchema,\n title,\n summary: z.string().max(2000).default(\"\"),\n kind: z.enum([\"text\", \"video\", \"audio\", \"quiz\", \"assignment\", \"live\"]).default(\"text\"),\n body: text.default(\"\"),\n portableText: z.array(z.record(z.string(), z.unknown())).max(1000).default([]),\n contentSource: z\n .object({ collection: idSchema, id: idSchema, field: idSchema.default(\"content\") })\n .nullable()\n .default(null),\n mediaUrl: safeUrlSchema.nullable().default(null),\n transcript: text.default(\"\"),\n captions: z\n .array(\n z.object({\n src: safeUrlSchema,\n language: z\n .string()\n .regex(/^[a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})*$/)\n .max(35),\n label: title,\n }),\n )\n .max(20)\n .default([]),\n liveStartsAt: timestamp.nullable().default(null),\n durationMinutes: z.number().int().min(0).max(1440).default(10),\n minStudySeconds: z.number().int().min(0).max(86400).default(0),\n preview: z.boolean().default(false),\n required: z.boolean().default(true),\n resources: z.array(resourceSchema).max(30).default([]),\n quiz: quizSchema.nullable().default(null),\n assignment: assignmentSchema.nullable().default(null),\n })\n .superRefine((lesson, ctx) => {\n if (lesson.kind === \"quiz\" && !lesson.quiz)\n ctx.addIssue({ code: \"custom\", message: \"Quiz lessons need a quiz.\" });\n if (lesson.kind === \"assignment\" && !lesson.assignment)\n ctx.addIssue({ code: \"custom\", message: \"Assignment lessons need an assignment.\" });\n if ([\"video\", \"audio\", \"live\"].includes(lesson.kind) && !lesson.mediaUrl)\n ctx.addIssue({ code: \"custom\", message: \"Media and live lessons need a URL.\" });\n if (lesson.kind === \"live\" && !lesson.liveStartsAt)\n ctx.addIssue({ code: \"custom\", message: \"Live lessons need a start time.\" });\n if (new Set(lesson.resources.map((resource) => resource.id)).size !== lesson.resources.length)\n ctx.addIssue({ code: \"custom\", message: \"Resource IDs must be unique.\" });\n });\n\nexport const moduleSchema = z.object({\n id: idSchema,\n title,\n description: z.string().max(2000).default(\"\"),\n releaseDays: z.number().int().min(0).max(3650).default(0),\n unlockAt: timestamp.nullable().default(null),\n lessons: z.array(lessonSchema).max(100).default([]),\n});\n\nexport const courseDataSchema = z\n .object({\n slug: z\n .string()\n .trim()\n .min(1)\n .max(100)\n .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, \"Use lowercase words separated by hyphens.\"),\n title,\n summary: z.string().trim().max(1000).default(\"\"),\n description: text.default(\"\"),\n outcomes: z.array(z.string().trim().min(1).max(500)).max(30).default([]),\n requirements: z.array(z.string().trim().min(1).max(500)).max(30).default([]),\n category: z.string().trim().max(100).default(\"\"),\n tags: z.array(z.string().trim().min(1).max(60)).max(20).default([]),\n language: z.string().trim().min(2).max(35).default(\"en\"),\n level: z.enum([\"beginner\", \"intermediate\", \"advanced\", \"all\"]).default(\"all\"),\n featuredImage: z\n .object({\n id: z.string().max(128).default(\"\"),\n src: safeUrlSchema,\n alt: z.string().max(500).default(\"\"),\n })\n .nullable()\n .default(null),\n instructorName: z.string().trim().max(200).default(\"\"),\n instructorIds: z.array(idSchema).max(20).default([]),\n status: z.enum([\"draft\", \"published\", \"archived\"]).default(\"draft\"),\n enrollmentMode: z.enum([\"open\", \"approval\", \"invite\"]).default(\"open\"),\n commerce: z\n .object({\n accessModel: z.enum([\"free\", \"paid\"]).default(\"free\"),\n offerId: idSchema.nullable().default(null),\n priceMinor: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).nullable().default(null),\n currency: z\n .string()\n .regex(/^[A-Z]{3}$/)\n .default(\"INR\"),\n })\n .default({ accessModel: \"free\", offerId: null, priceMinor: null, currency: \"INR\" }),\n prerequisiteCourseIds: z.array(idSchema).max(20).default([]),\n sequential: z.boolean().default(true),\n enrollmentClosesAt: timestamp.nullable().default(null),\n accessDays: z.number().int().min(0).max(3650).default(0),\n certificateEnabled: z.boolean().default(true),\n modules: z.array(moduleSchema).max(50).default([]),\n })\n .superRefine((course, ctx) => {\n const allIds = course.modules.flatMap((module) => [\n module.id,\n ...module.lessons.map((lesson) => lesson.id),\n ]);\n if (new Set(allIds).size !== allIds.length)\n ctx.addIssue({\n code: \"custom\",\n message: \"Module and lesson IDs must be unique across the course.\",\n });\n if (course.modules.flatMap((module) => module.lessons).length > 150)\n ctx.addIssue({ code: \"custom\", message: \"A course supports up to 150 lessons.\" });\n if (\n course.status === \"published\" &&\n !course.modules.some((module) => module.lessons.some((lesson) => lesson.required))\n )\n ctx.addIssue({\n code: \"custom\",\n message: \"Publish a course with at least one required lesson.\",\n });\n });\n\nexport const courseSaveSchema = z.object({\n id: idSchema.optional(),\n expectedRevision: z.string().max(128).nullable().default(null),\n data: courseDataSchema,\n});\nexport const pageSchema = z.object({\n cursor: z.string().max(4000).optional(),\n limit: z.coerce.number().int().min(1).max(100).default(24),\n});\nexport const catalogSchema = pageSchema.extend({\n q: z.string().max(100).default(\"\"),\n category: z.string().max(100).default(\"\"),\n level: z.enum([\"beginner\", \"intermediate\", \"advanced\", \"all\"]).optional(),\n language: z.string().max(35).optional(),\n});\nexport const courseIdSchema = z.object({ courseId: idSchema });\nexport const lessonIdSchema = courseIdSchema.extend({ lessonId: idSchema });\nexport const answersSchema = z.record(\n idSchema,\n z.union([z.string().max(2000), z.array(z.string().max(500)).max(10)]),\n);\nexport const quizSubmitSchema = lessonIdSchema.extend({\n attemptId: idSchema,\n answers: answersSchema,\n expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional(),\n});\nexport const quizDraftSchema = quizSubmitSchema.extend({\n expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),\n});\nexport const assignmentSubmitSchema = lessonIdSchema.extend({\n body: z.string().trim().min(1).max(20_000),\n attachmentUrl: safeUrlSchema.nullable().default(null),\n submissionId: idSchema.optional(),\n expectedDraftRevision: z\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER - 1)\n .optional(),\n});\nexport const assignmentDraftSchema = lessonIdSchema.extend({\n body: z.string().max(20_000).default(\"\"),\n attachmentUrl: safeUrlSchema.nullable().default(null),\n expectedDraftRevision: z\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER - 1),\n});\nexport const enrollmentRequestSchema = courseIdSchema.extend({ cohortId: idSchema.optional() });\nexport const enrollmentAdminSchema = courseIdSchema.extend({\n userId: idSchema,\n status: z.enum([\"active\", \"rejected\", \"suspended\", \"cancelled\"]),\n reason: z.string().max(1000).default(\"\"),\n cohortId: idSchema.nullable().optional(),\n accessStartsAt: timestamp.nullable().optional(),\n accessExpiresAt: timestamp.nullable().optional(),\n});\nexport const gradeSchema = lessonIdSchema.extend({\n userId: idSchema,\n submissionId: idSchema,\n points: z.number().int().min(0).max(1000).optional(),\n rubricScores: z.array(rubricScoreSchema).max(20).optional(),\n feedback: z.string().max(10_000).default(\"\"),\n});\nexport const discussionSchema = lessonIdSchema.extend({\n body: z.string().trim().min(1).max(5000),\n parentId: idSchema.nullable().default(null),\n});\nexport const reviewSchema = courseIdSchema.extend({\n rating: z.number().int().min(1).max(5),\n body: z.string().trim().min(1).max(3000),\n});\nexport const moderateSchema = z.object({\n id: keySchema,\n status: z.enum([\"published\", \"hidden\"]),\n expectedRevision: z.string().min(1).max(128),\n});\nexport const cohortDataSchema = z\n .object({\n title,\n courseIds: z.array(idSchema).min(1).max(20),\n memberIds: z.array(idSchema).max(1000).default([]),\n startsAt: timestamp.nullable().default(null),\n endsAt: timestamp.nullable().default(null),\n })\n .refine(\n (cohort) =>\n !cohort.startsAt || !cohort.endsAt || Date.parse(cohort.endsAt) > Date.parse(cohort.startsAt),\n \"Cohort end must follow its start.\",\n )\n .refine(\n (cohort) => new Set(cohort.memberIds).size === cohort.memberIds.length,\n \"Cohort members must be unique.\",\n )\n .refine(\n (cohort) => new Set(cohort.courseIds).size === cohort.courseIds.length,\n \"Cohort courses must be unique.\",\n );\nexport const cohortSaveSchema = z.object({\n id: idSchema.optional(),\n expectedRevision: z.string().max(128).nullable().default(null),\n data: cohortDataSchema,\n});\nexport const settingsSchema = z.object({\n academyTitle: title.default(\"Ananta Gnanam Academy\"),\n academyDescription: z.string().max(2000).default(\"Build knowledge, one lesson at a time.\"),\n issuerName: title.default(\"Ananta Gnanam\"),\n moderateDiscussions: z.boolean().default(true),\n moderateReviews: z.boolean().default(true),\n emailNotifications: z.boolean().default(false),\n reminderDays: z.number().int().min(0).max(90).default(7),\n});\nexport const certificateActionSchema = courseIdSchema.extend({ shared: z.boolean() });\nexport const certificateRevokeSchema = courseIdSchema.extend({\n userId: idSchema,\n reason: z.string().trim().min(1).max(1000),\n});\nexport const noteSchema = lessonIdSchema.extend({\n note: z.string().max(10_000),\n expectedRevision: z\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER - 1)\n .default(0),\n});\nexport const studyNoteSchema = lessonIdSchema\n .extend({\n id: idSchema,\n body: z.string().max(5000),\n positionSeconds: z.number().min(0).max(86_400).nullable().default(null),\n starred: z.boolean().default(false),\n archived: z.boolean().default(false),\n expectedRevision: z\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER - 1),\n })\n .refine(\n (note) => note.body.trim().length > 0 || note.positionSeconds !== null,\n \"Write a note or choose a media timestamp.\",\n );\n\nexport const preferencesSchema = z.object({\n emailNotifications: z.boolean().default(true),\n weeklyGoalLessons: z.number().int().min(0).max(100).default(3),\n});\nexport const playbackSchema = lessonIdSchema.extend({\n positionSeconds: z.number().finite().min(0).max(86_400),\n playbackRate: z.number().min(0.25).max(3),\n expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER),\n});\nexport const pathDataSchema = z.object({\n title,\n description: z.string().max(5000).default(\"\"),\n courseIds: z\n .array(idSchema)\n .min(1)\n .max(30)\n .refine((ids) => new Set(ids).size === ids.length, \"Courses must be unique.\"),\n status: z.enum([\"draft\", \"published\", \"archived\"]).default(\"draft\"),\n});\nexport const pathSaveSchema = z.object({\n id: idSchema.optional(),\n expectedRevision: z.string().max(128).nullable().default(null),\n data: pathDataSchema,\n});\n"],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import { CourseDetail, Lesson, LessonProgress, PublicLesson } from "./types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/assignments.d.ts
|
|
4
|
+
declare function assignmentBlock(assignment: NonNullable<Lesson["assignment"]>, progress: Pick<LessonProgress, "completedAt" | "assignments">, now: Date): {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
status: number;
|
|
8
|
+
} | null;
|
|
9
|
+
//#endregion
|
|
1
10
|
//#region src/errors.d.ts
|
|
2
11
|
declare class LmsError extends Error {
|
|
3
12
|
readonly code: string;
|
|
@@ -22,9 +31,17 @@ interface RuntimeLocals {
|
|
|
22
31
|
declare function lmsPublic<T>(locals: RuntimeLocals, route: string, input: Record<string, unknown>, origin: string): Promise<T>;
|
|
23
32
|
declare function lmsLearner<T>(locals: RuntimeLocals, route: string, input: Record<string, unknown>, origin: string): Promise<T>;
|
|
24
33
|
declare function loginUrl(loginPath: string, returnTo: string): string;
|
|
34
|
+
/** A fixed private read route; authorization remains at the EmDash runtime boundary. */
|
|
35
|
+
declare function lmsAuthorLessonPreview(locals: RuntimeLocals, input: {
|
|
36
|
+
courseId: string;
|
|
37
|
+
lessonId: string;
|
|
38
|
+
}, origin: string): Promise<{
|
|
39
|
+
course: CourseDetail;
|
|
40
|
+
lesson: PublicLesson;
|
|
41
|
+
}>;
|
|
25
42
|
declare function courseUrl(basePath: string, slug: string): string;
|
|
26
43
|
declare function lessonUrl(basePath: string, slug: string, lessonId: string): string;
|
|
27
44
|
declare function certificateUrl(basePath: string, id: string): string;
|
|
28
45
|
//#endregion
|
|
29
|
-
export { LmsError, certificateUrl, courseUrl, lessonUrl, lmsLearner, lmsPublic, loginUrl };
|
|
46
|
+
export { LmsError, assignmentBlock, certificateUrl, courseUrl, lessonUrl, lmsAuthorLessonPreview, lmsLearner, lmsPublic, loginUrl };
|
|
30
47
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as PLUGIN_ID } from "./constants-
|
|
2
|
-
import {
|
|
1
|
+
import { r as PLUGIN_ID } from "./constants-DyQbwNbP.js";
|
|
2
|
+
import { i as LmsError, t as assignmentBlock } from "./assignments-CsuAjxGO.js";
|
|
3
3
|
|
|
4
4
|
//#region src/server.ts
|
|
5
5
|
function requestUrl(route, input, origin) {
|
|
@@ -18,6 +18,12 @@ async function lmsPublic(locals, route, input, origin) {
|
|
|
18
18
|
return unwrap(await dispatch(PLUGIN_ID, "GET", route, new Request(requestUrl(route, input, origin))));
|
|
19
19
|
}
|
|
20
20
|
const READ_ROUTES = new Set([
|
|
21
|
+
"learner/study/courses",
|
|
22
|
+
"learner/notebook",
|
|
23
|
+
"learner/agenda",
|
|
24
|
+
"learner/paths",
|
|
25
|
+
"learner/saved",
|
|
26
|
+
"learner/preferences",
|
|
21
27
|
"learner/dashboard",
|
|
22
28
|
"learner/course",
|
|
23
29
|
"learner/course-by-slug",
|
|
@@ -39,6 +45,14 @@ function loginUrl(loginPath, returnTo) {
|
|
|
39
45
|
url.searchParams.set("redirect", returnTo);
|
|
40
46
|
return `${url.pathname}${url.search}${url.hash}`;
|
|
41
47
|
}
|
|
48
|
+
/** A fixed private read route; authorization remains at the EmDash runtime boundary. */
|
|
49
|
+
async function lmsAuthorLessonPreview(locals, input, origin) {
|
|
50
|
+
if (!locals.user) throw new LmsError("UNAUTHORIZED", "Sign in to preview this lesson.", 401);
|
|
51
|
+
const dispatch = locals.emdash?.handlePluginApiRoute;
|
|
52
|
+
if (!dispatch) throw new LmsError("LMS_UNAVAILABLE", "The learning service is unavailable.", 503);
|
|
53
|
+
const route = "admin/lesson/preview";
|
|
54
|
+
return unwrap(await dispatch(PLUGIN_ID, "GET", route, new Request(requestUrl(route, input, origin)), locals.user));
|
|
55
|
+
}
|
|
42
56
|
function courseUrl(basePath, slug) {
|
|
43
57
|
return `${basePath}/courses/${encodeURIComponent(slug)}`;
|
|
44
58
|
}
|
|
@@ -50,5 +64,5 @@ function certificateUrl(basePath, id) {
|
|
|
50
64
|
}
|
|
51
65
|
|
|
52
66
|
//#endregion
|
|
53
|
-
export { LmsError, certificateUrl, courseUrl, lessonUrl, lmsLearner, lmsPublic, loginUrl };
|
|
67
|
+
export { LmsError, assignmentBlock, certificateUrl, courseUrl, lessonUrl, lmsAuthorLessonPreview, lmsLearner, lmsPublic, loginUrl };
|
|
54
68
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","names":[],"sources":["../src/server.ts"],"sourcesContent":["import { PLUGIN_ID } from \"./constants.js\";\nimport { LmsError } from \"./errors.js\";\nimport type { RouteEnvelope } from \"./types.js\";\n\ninterface RuntimeLocals {\n user?: { id: string; email: string; name: string | null; role: number; createdAt: Date | string };\n emdash?: {\n handlePublicPluginApiRoute?: (\n pluginId: string,\n method: string,\n path: string,\n request: Request,\n ) => Promise<unknown>;\n handlePluginApiRoute?: (\n pluginId: string,\n method: string,\n path: string,\n request: Request,\n user?: RuntimeLocals[\"user\"] | null,\n ) => Promise<unknown>;\n };\n}\n\nfunction requestUrl(route: string, input: Record<string, unknown>, origin: string): URL {\n const url = new URL(`/_emdash/api/plugins/${PLUGIN_ID}/${route}`, origin);\n for (const [key, value] of Object.entries(input))\n if (value !== undefined && value !== null && value !== \"\")\n url.searchParams.set(key, String(value));\n return url;\n}\nfunction unwrap<T>(input: unknown): T {\n const result = input as RouteEnvelope<T>;\n if (!result?.success)\n throw new LmsError(\n result?.error?.code ?? \"LMS_UNAVAILABLE\",\n result?.error?.message ?? \"The learning service is unavailable.\",\n result?.status ?? 503,\n );\n return result.data as T;\n}\nexport async function lmsPublic<T>(\n locals: RuntimeLocals,\n route: string,\n input: Record<string, unknown>,\n origin: string,\n): Promise<T> {\n const dispatch = locals.emdash?.handlePublicPluginApiRoute;\n if (!dispatch) throw new LmsError(\"LMS_UNAVAILABLE\", \"The learning service is unavailable.\", 503);\n return unwrap<T>(\n await dispatch(PLUGIN_ID, \"GET\", route, new Request(requestUrl(route, input, origin))),\n );\n}\nconst READ_ROUTES = new Set([\n \"learner/dashboard\",\n \"learner/course\",\n \"learner/course-by-slug\",\n \"learner/lesson\",\n \"learner/certificate\",\n \"learner/certificate-by-id\",\n \"learner/cohort\",\n \"learner/notifications\",\n]);\nexport async function lmsLearner<T>(\n locals: RuntimeLocals,\n route: string,\n input: Record<string, unknown>,\n origin: string,\n): Promise<T> {\n if (!locals.user || locals.user.role < 10)\n throw new LmsError(\"UNAUTHORIZED\", \"Sign in to continue.\", 401);\n if (!READ_ROUTES.has(route))\n throw new LmsError(\"FORBIDDEN\", \"This route is not available to the learner renderer.\", 403);\n const dispatch = locals.emdash?.handlePluginApiRoute;\n if (!dispatch) throw new LmsError(\"LMS_UNAVAILABLE\", \"The learning service is unavailable.\", 503);\n return unwrap<T>(\n await dispatch(\n PLUGIN_ID,\n \"GET\",\n route,\n new Request(requestUrl(route, input, origin)),\n locals.user,\n ),\n );\n}\nexport function loginUrl(loginPath: string, returnTo: string): string {\n const url = new URL(loginPath, \"https://lms.invalid\");\n url.searchParams.set(\"redirect\", returnTo);\n return `${url.pathname}${url.search}${url.hash}`;\n}\nexport function courseUrl(basePath: string, slug: string): string {\n return `${basePath}/courses/${encodeURIComponent(slug)}`;\n}\nexport function lessonUrl(basePath: string, slug: string, lessonId: string): string {\n return `${courseUrl(basePath, slug)}/lessons/${encodeURIComponent(lessonId)}`;\n}\nexport function certificateUrl(basePath: string, id: string): string {\n return `${basePath}/certificates/${encodeURIComponent(id)}`;\n}\nexport { LmsError } from \"./errors.js\";\n"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"server.js","names":[],"sources":["../src/server.ts"],"sourcesContent":["import { PLUGIN_ID } from \"./constants.js\";\nexport { assignmentBlock } from \"./assignments.js\";\nimport { LmsError } from \"./errors.js\";\nimport type { CourseDetail, PublicLesson, RouteEnvelope } from \"./types.js\";\n\ninterface RuntimeLocals {\n user?: { id: string; email: string; name: string | null; role: number; createdAt: Date | string };\n emdash?: {\n handlePublicPluginApiRoute?: (\n pluginId: string,\n method: string,\n path: string,\n request: Request,\n ) => Promise<unknown>;\n handlePluginApiRoute?: (\n pluginId: string,\n method: string,\n path: string,\n request: Request,\n user?: RuntimeLocals[\"user\"] | null,\n ) => Promise<unknown>;\n };\n}\n\nfunction requestUrl(route: string, input: Record<string, unknown>, origin: string): URL {\n const url = new URL(`/_emdash/api/plugins/${PLUGIN_ID}/${route}`, origin);\n for (const [key, value] of Object.entries(input))\n if (value !== undefined && value !== null && value !== \"\")\n url.searchParams.set(key, String(value));\n return url;\n}\nfunction unwrap<T>(input: unknown): T {\n const result = input as RouteEnvelope<T>;\n if (!result?.success)\n throw new LmsError(\n result?.error?.code ?? \"LMS_UNAVAILABLE\",\n result?.error?.message ?? \"The learning service is unavailable.\",\n result?.status ?? 503,\n );\n return result.data as T;\n}\nexport async function lmsPublic<T>(\n locals: RuntimeLocals,\n route: string,\n input: Record<string, unknown>,\n origin: string,\n): Promise<T> {\n const dispatch = locals.emdash?.handlePublicPluginApiRoute;\n if (!dispatch) throw new LmsError(\"LMS_UNAVAILABLE\", \"The learning service is unavailable.\", 503);\n return unwrap<T>(\n await dispatch(PLUGIN_ID, \"GET\", route, new Request(requestUrl(route, input, origin))),\n );\n}\nconst READ_ROUTES = new Set([\n \"learner/study/courses\",\n \"learner/notebook\",\n \"learner/agenda\",\n \"learner/paths\",\n \"learner/saved\",\n \"learner/preferences\",\n \"learner/dashboard\",\n \"learner/course\",\n \"learner/course-by-slug\",\n \"learner/lesson\",\n \"learner/certificate\",\n \"learner/certificate-by-id\",\n \"learner/cohort\",\n \"learner/notifications\",\n]);\nexport async function lmsLearner<T>(\n locals: RuntimeLocals,\n route: string,\n input: Record<string, unknown>,\n origin: string,\n): Promise<T> {\n if (!locals.user || locals.user.role < 10)\n throw new LmsError(\"UNAUTHORIZED\", \"Sign in to continue.\", 401);\n if (!READ_ROUTES.has(route))\n throw new LmsError(\"FORBIDDEN\", \"This route is not available to the learner renderer.\", 403);\n const dispatch = locals.emdash?.handlePluginApiRoute;\n if (!dispatch) throw new LmsError(\"LMS_UNAVAILABLE\", \"The learning service is unavailable.\", 503);\n return unwrap<T>(\n await dispatch(\n PLUGIN_ID,\n \"GET\",\n route,\n new Request(requestUrl(route, input, origin)),\n locals.user,\n ),\n );\n}\nexport function loginUrl(loginPath: string, returnTo: string): string {\n const url = new URL(loginPath, \"https://lms.invalid\");\n url.searchParams.set(\"redirect\", returnTo);\n return `${url.pathname}${url.search}${url.hash}`;\n}\n/** A fixed private read route; authorization remains at the EmDash runtime boundary. */\nexport async function lmsAuthorLessonPreview(\n locals: RuntimeLocals,\n input: { courseId: string; lessonId: string },\n origin: string,\n): Promise<{ course: CourseDetail; lesson: PublicLesson }> {\n if (!locals.user) throw new LmsError(\"UNAUTHORIZED\", \"Sign in to preview this lesson.\", 401);\n const dispatch = locals.emdash?.handlePluginApiRoute;\n if (!dispatch) throw new LmsError(\"LMS_UNAVAILABLE\", \"The learning service is unavailable.\", 503);\n const route = \"admin/lesson/preview\";\n return unwrap(\n await dispatch(\n PLUGIN_ID,\n \"GET\",\n route,\n new Request(requestUrl(route, input, origin)),\n locals.user,\n ),\n );\n}\nexport function courseUrl(basePath: string, slug: string): string {\n return `${basePath}/courses/${encodeURIComponent(slug)}`;\n}\nexport function lessonUrl(basePath: string, slug: string, lessonId: string): string {\n return `${courseUrl(basePath, slug)}/lessons/${encodeURIComponent(lessonId)}`;\n}\nexport function certificateUrl(basePath: string, id: string): string {\n return `${basePath}/certificates/${encodeURIComponent(id)}`;\n}\nexport { LmsError } from \"./errors.js\";\n"],"mappings":";;;;AAwBA,SAAS,WAAW,OAAe,OAAgC,QAAqB;CACtF,MAAM,MAAM,IAAI,IAAI,wBAAwB,UAAU,GAAG,SAAS,OAAO;AACzE,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,KAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GACrD,KAAI,aAAa,IAAI,KAAK,OAAO,MAAM,CAAC;AAC5C,QAAO;;AAET,SAAS,OAAU,OAAmB;CACpC,MAAM,SAAS;AACf,KAAI,CAAC,QAAQ,QACX,OAAM,IAAI,SACR,QAAQ,OAAO,QAAQ,mBACvB,QAAQ,OAAO,WAAW,wCAC1B,QAAQ,UAAU,IACnB;AACH,QAAO,OAAO;;AAEhB,eAAsB,UACpB,QACA,OACA,OACA,QACY;CACZ,MAAM,WAAW,OAAO,QAAQ;AAChC,KAAI,CAAC,SAAU,OAAM,IAAI,SAAS,mBAAmB,wCAAwC,IAAI;AACjG,QAAO,OACL,MAAM,SAAS,WAAW,OAAO,OAAO,IAAI,QAAQ,WAAW,OAAO,OAAO,OAAO,CAAC,CAAC,CACvF;;AAEH,MAAM,cAAc,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AACF,eAAsB,WACpB,QACA,OACA,OACA,QACY;AACZ,KAAI,CAAC,OAAO,QAAQ,OAAO,KAAK,OAAO,GACrC,OAAM,IAAI,SAAS,gBAAgB,wBAAwB,IAAI;AACjE,KAAI,CAAC,YAAY,IAAI,MAAM,CACzB,OAAM,IAAI,SAAS,aAAa,wDAAwD,IAAI;CAC9F,MAAM,WAAW,OAAO,QAAQ;AAChC,KAAI,CAAC,SAAU,OAAM,IAAI,SAAS,mBAAmB,wCAAwC,IAAI;AACjG,QAAO,OACL,MAAM,SACJ,WACA,OACA,OACA,IAAI,QAAQ,WAAW,OAAO,OAAO,OAAO,CAAC,EAC7C,OAAO,KACR,CACF;;AAEH,SAAgB,SAAS,WAAmB,UAA0B;CACpE,MAAM,MAAM,IAAI,IAAI,WAAW,sBAAsB;AACrD,KAAI,aAAa,IAAI,YAAY,SAAS;AAC1C,QAAO,GAAG,IAAI,WAAW,IAAI,SAAS,IAAI;;;AAG5C,eAAsB,uBACpB,QACA,OACA,QACyD;AACzD,KAAI,CAAC,OAAO,KAAM,OAAM,IAAI,SAAS,gBAAgB,mCAAmC,IAAI;CAC5F,MAAM,WAAW,OAAO,QAAQ;AAChC,KAAI,CAAC,SAAU,OAAM,IAAI,SAAS,mBAAmB,wCAAwC,IAAI;CACjG,MAAM,QAAQ;AACd,QAAO,OACL,MAAM,SACJ,WACA,OACA,OACA,IAAI,QAAQ,WAAW,OAAO,OAAO,OAAO,CAAC,EAC7C,OAAO,KACR,CACF;;AAEH,SAAgB,UAAU,UAAkB,MAAsB;AAChE,QAAO,GAAG,SAAS,WAAW,mBAAmB,KAAK;;AAExD,SAAgB,UAAU,UAAkB,MAAc,UAA0B;AAClF,QAAO,GAAG,UAAU,UAAU,KAAK,CAAC,WAAW,mBAAmB,SAAS;;AAE7E,SAAgB,eAAe,UAAkB,IAAoB;AACnE,QAAO,GAAG,SAAS,gBAAgB,mBAAmB,GAAG"}
|