@anantagnanam/lms 0.0.0-stage → 0.2.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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -2
  3. package/astro/client.ts +355 -0
  4. package/astro/components/CertificateCard.astro +83 -0
  5. package/astro/components/CourseCard.astro +61 -0
  6. package/astro/components/CourseCatalog.astro +96 -0
  7. package/astro/components/CourseOverview.astro +308 -0
  8. package/astro/components/LearnerDashboard.astro +127 -0
  9. package/astro/components/LearningShell.astro +37 -0
  10. package/astro/components/LessonAvailabilityNote.astro +26 -0
  11. package/astro/components/LessonContent.astro +53 -0
  12. package/astro/components/LessonPlayer.astro +302 -0
  13. package/astro/components/MediaPlayer.astro +111 -0
  14. package/astro/components/index.ts +7 -0
  15. package/astro/layouts/AcademyLayout.astro +84 -0
  16. package/astro/media-player.ts +99 -0
  17. package/astro/pages/author-preview.astro +71 -0
  18. package/astro/pages/certificate.astro +57 -0
  19. package/astro/pages/cohort.astro +102 -0
  20. package/astro/pages/course.astro +90 -0
  21. package/astro/pages/dashboard.astro +34 -0
  22. package/astro/pages/index.astro +40 -0
  23. package/astro/pages/lesson.astro +103 -0
  24. package/astro/pages/library.astro +173 -0
  25. package/astro/pages/paths.astro +73 -0
  26. package/astro/pages/teach.astro +15 -0
  27. package/astro/quiz-drafts.ts +87 -0
  28. package/astro/quiz-player.ts +362 -0
  29. package/astro/styles.css +1300 -0
  30. package/dist/admin.d.ts +34 -0
  31. package/dist/admin.js +3231 -0
  32. package/dist/admin.js.map +1 -0
  33. package/dist/astro.d.ts +11 -0
  34. package/dist/astro.js +52 -0
  35. package/dist/astro.js.map +1 -0
  36. package/dist/commerce.d.ts +72 -0
  37. package/dist/commerce.js +0 -0
  38. package/dist/config-BX3beTpM.js +15 -0
  39. package/dist/config-BX3beTpM.js.map +1 -0
  40. package/dist/constants-Cnx7k82Z.js +161 -0
  41. package/dist/constants-Cnx7k82Z.js.map +1 -0
  42. package/dist/csv-DKq_4OWU.js +55 -0
  43. package/dist/csv-DKq_4OWU.js.map +1 -0
  44. package/dist/errors-ChzJS9al.js +16 -0
  45. package/dist/errors-ChzJS9al.js.map +1 -0
  46. package/dist/index.d.ts +13 -0
  47. package/dist/index.js +19 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/runtime.d.ts +773 -0
  50. package/dist/runtime.js +2840 -0
  51. package/dist/runtime.js.map +1 -0
  52. package/dist/schemas.d.ts +651 -0
  53. package/dist/schemas.js +347 -0
  54. package/dist/schemas.js.map +1 -0
  55. package/dist/server.d.ts +40 -0
  56. package/dist/server.js +65 -0
  57. package/dist/server.js.map +1 -0
  58. package/dist/types.d.ts +387 -0
  59. package/dist/types.js +0 -0
  60. package/package.json +83 -4
@@ -0,0 +1,387 @@
1
+ import { cohortDataSchema, courseDataSchema, lessonSchema, moduleSchema, pathDataSchema, preferencesSchema, questionSchema, quizSchema, settingsSchema } from "./schemas.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/types.d.ts
5
+ type CourseData = z.infer<typeof courseDataSchema>;
6
+ type CourseModule = z.infer<typeof moduleSchema>;
7
+ type Lesson = z.infer<typeof lessonSchema>;
8
+ type QuizQuestion = z.infer<typeof questionSchema>;
9
+ type Quiz = z.infer<typeof quizSchema>;
10
+ type LmsSettings = z.infer<typeof settingsSchema>;
11
+ interface Course extends CourseData {
12
+ id: string;
13
+ searchTitle: string;
14
+ createdBy: string;
15
+ createdAt: string;
16
+ updatedAt: string;
17
+ schemaVersion: 1 | 2;
18
+ draftRevisionId?: string;
19
+ publishedEditionId?: string;
20
+ publishedDraftRevisionId?: string;
21
+ legacyEditionId?: string;
22
+ }
23
+ interface CourseRevision {
24
+ id: string;
25
+ courseId: string;
26
+ parentId: string | null;
27
+ data: CourseData;
28
+ kind: "migration" | "draft" | "publish" | "restore" | "archive";
29
+ createdBy: string;
30
+ createdAt: string;
31
+ editionId?: string;
32
+ restoredFrom?: string;
33
+ }
34
+ type RevisionSummary = Omit<CourseRevision, "data"> & {
35
+ title: string;
36
+ };
37
+ interface CourseEdition {
38
+ id: string;
39
+ courseId: string;
40
+ data: CourseData;
41
+ createdAt: string;
42
+ }
43
+ interface MigrationState {
44
+ phase: "courses" | "enrollments" | "complete";
45
+ cursor?: string;
46
+ coursesProcessed: number;
47
+ enrollmentsProcessed: number;
48
+ updatedAt: string;
49
+ lastError: string | null;
50
+ }
51
+ interface Actor {
52
+ id: string;
53
+ email: string;
54
+ name: string | null;
55
+ role: number;
56
+ }
57
+ interface Versioned<T> {
58
+ value: T;
59
+ revision: string;
60
+ }
61
+ type Answers = Record<string, string | string[]>;
62
+ type PublicQuestion = Omit<QuizQuestion, "correctAnswers" | "explanation">;
63
+ interface QuestionResult {
64
+ questionId: string;
65
+ correct: boolean;
66
+ points: number;
67
+ maxPoints: number;
68
+ explanation?: string;
69
+ }
70
+ interface QuizAttempt {
71
+ id: string;
72
+ startedAt: string;
73
+ expiresAt: string | null;
74
+ status: "in_progress" | "submitted" | "expired";
75
+ quiz: Quiz | null;
76
+ questions: PublicQuestion[];
77
+ submittedAt: string | null;
78
+ score: number | null;
79
+ maxScore: number | null;
80
+ percent: number | null;
81
+ passed: boolean;
82
+ feedback: QuestionResult[];
83
+ answers: Answers;
84
+ /** Records created before draft fencing have revision zero. */
85
+ draftRevision?: number;
86
+ }
87
+ type PublicQuizAttempt = Omit<QuizAttempt, "quiz" | "draftRevision"> & {
88
+ draftRevision: number;
89
+ };
90
+ interface AssignmentSubmission {
91
+ id: string;
92
+ body: string;
93
+ attachmentUrl: string | null;
94
+ submittedAt: string;
95
+ status: "submitted" | "graded";
96
+ maxPoints: number;
97
+ passingPoints: number;
98
+ points: number | null;
99
+ feedback: string;
100
+ gradedAt: string | null;
101
+ gradedBy: string | null;
102
+ }
103
+ interface LessonProgress {
104
+ startedAt: string | null;
105
+ completedAt: string | null;
106
+ note: string;
107
+ quizAttempts: QuizAttempt[];
108
+ assignments: AssignmentSubmission[];
109
+ playback?: Playback;
110
+ }
111
+ interface Playback {
112
+ positionSeconds: number;
113
+ playbackRate: number;
114
+ revision: number;
115
+ updatedAt: string;
116
+ }
117
+ type LearnerPreferences = z.infer<typeof preferencesSchema>;
118
+ interface SavedCourse {
119
+ userId: string;
120
+ courseId: string;
121
+ saved: boolean;
122
+ updatedAt: string;
123
+ }
124
+ interface LearningPath extends z.infer<typeof pathDataSchema> {
125
+ id: string;
126
+ createdAt: string;
127
+ updatedAt: string;
128
+ }
129
+ interface PathEnrollment {
130
+ pathId: string;
131
+ userId: string;
132
+ title: string;
133
+ courseIds: string[];
134
+ joinedAt: string;
135
+ }
136
+ interface PublicPath {
137
+ id: string;
138
+ title: string;
139
+ description: string;
140
+ courses: (CourseCard | null)[];
141
+ }
142
+ interface LearnerPath {
143
+ pathId: string;
144
+ title: string;
145
+ joinedAt: string;
146
+ completed: number;
147
+ total: number;
148
+ courses: {
149
+ course: CourseCard | null;
150
+ completed: boolean;
151
+ }[];
152
+ }
153
+ interface LmsHealth {
154
+ version: string;
155
+ maintenance: {
156
+ startedAt: string;
157
+ completedAt: string | null;
158
+ failed: boolean;
159
+ } | null;
160
+ maintenanceStale: boolean;
161
+ pendingEmails: number;
162
+ failedEmails: number;
163
+ oldestPendingAt: string | null;
164
+ emailEnabled: boolean;
165
+ migration: MigrationState | null;
166
+ }
167
+ interface Certificate {
168
+ id: string;
169
+ courseId: string;
170
+ courseTitle: string;
171
+ userId: string;
172
+ learnerName: string;
173
+ issuerName: string;
174
+ issuedAt: string;
175
+ shared: boolean;
176
+ revokedAt: string | null;
177
+ revocationReason: string | null;
178
+ }
179
+ interface Enrollment {
180
+ id: string;
181
+ courseId: string;
182
+ /** Immutable curriculum selected at enrollment; v1 records use the course's legacy edition. */
183
+ courseEditionId?: string;
184
+ userId: string;
185
+ learnerName: string;
186
+ learnerEmail: string;
187
+ status: "pending" | "active" | "completed" | "rejected" | "suspended" | "cancelled";
188
+ accessStatus: "pending" | "granted" | "suspended" | "revoked";
189
+ accessSource: "free" | "manual" | "cohort" | "purchase";
190
+ grants: Record<string, AccessGrant>;
191
+ cohortIds: string[];
192
+ acquisition: Acquisition;
193
+ approvedBy: string | null;
194
+ decisionAt: string | null;
195
+ decisionReason: string | null;
196
+ enrolledAt: string;
197
+ approvedAt: string | null;
198
+ completedAt: string | null;
199
+ accessStartsAt: string | null;
200
+ accessExpiresAt: string | null;
201
+ cohortId: string | null;
202
+ progress: Record<string, LessonProgress>;
203
+ certificate: Certificate | null;
204
+ completionLessonIds: string[];
205
+ lastActivityAt: string;
206
+ schemaVersion: 1;
207
+ }
208
+ interface Acquisition {
209
+ orderId: string | null;
210
+ offerId: string | null;
211
+ paymentStatus: "not_required" | "pending" | "paid" | "partially_refunded" | "refunded" | "cancelled";
212
+ amountMinor: number | null;
213
+ currency: string | null;
214
+ providerId: string | null;
215
+ providerPaymentId: string | null;
216
+ }
217
+ interface AccessGrant {
218
+ id: string;
219
+ source: Enrollment["accessSource"];
220
+ referenceId: string | null;
221
+ status: "pending" | "granted" | "suspended" | "revoked";
222
+ startsAt: string | null;
223
+ expiresAt: string | null;
224
+ grantedBy: string | null;
225
+ grantedAt: string | null;
226
+ }
227
+ interface PublicEnrollment extends Omit<Enrollment, "learnerEmail" | "progress"> {
228
+ effectiveAccess: "pending" | "granted" | "scheduled" | "expired" | "suspended" | "revoked";
229
+ progress: Record<string, Omit<LessonProgress, "quizAttempts"> & {
230
+ quizAttempts: PublicQuizAttempt[];
231
+ }>;
232
+ }
233
+ interface CertificateIndex {
234
+ enrollmentId: string;
235
+ userId: string;
236
+ courseId: string;
237
+ }
238
+ interface Discussion {
239
+ id: string;
240
+ courseId: string;
241
+ lessonId: string;
242
+ parentId: string | null;
243
+ authorId: string;
244
+ authorName: string;
245
+ body: string;
246
+ status: "pending" | "published" | "hidden";
247
+ createdAt: string;
248
+ updatedAt: string;
249
+ }
250
+ interface Review {
251
+ id: string;
252
+ courseId: string;
253
+ userId: string;
254
+ authorName: string;
255
+ rating: number;
256
+ body: string;
257
+ status: "pending" | "published" | "hidden";
258
+ createdAt: string;
259
+ updatedAt: string;
260
+ }
261
+ interface Cohort extends z.infer<typeof cohortDataSchema> {
262
+ id: string;
263
+ createdBy: string;
264
+ createdAt: string;
265
+ updatedAt: string;
266
+ }
267
+ interface CohortMembership {
268
+ id: string;
269
+ cohortId: string;
270
+ userId: string;
271
+ learnerName: string;
272
+ learnerEmail: string;
273
+ status: "pending" | "active" | "rejected" | "suspended" | "cancelled";
274
+ requestedAt: string;
275
+ decidedAt: string | null;
276
+ decidedBy: string | null;
277
+ reason: string | null;
278
+ }
279
+ interface Notification {
280
+ id: string;
281
+ userId: string;
282
+ email: string;
283
+ title: string;
284
+ message: string;
285
+ courseId: string | null;
286
+ read: boolean;
287
+ createdAt: string;
288
+ emailStatus: "pending" | "sending" | "sent" | "disabled" | "failed";
289
+ emailAttempts: number;
290
+ claimedAt: string | null;
291
+ }
292
+ interface AuditRecord {
293
+ id: string;
294
+ actorId: string;
295
+ action: string;
296
+ resourceId: string;
297
+ createdAt: string;
298
+ details: Record<string, unknown>;
299
+ }
300
+ interface CourseCard {
301
+ id: string;
302
+ slug: string;
303
+ title: string;
304
+ summary: string;
305
+ category: string;
306
+ tags: string[];
307
+ level: CourseData["level"];
308
+ language: string;
309
+ featuredImage: CourseData["featuredImage"];
310
+ instructorName: string;
311
+ enrollmentMode: CourseData["enrollmentMode"];
312
+ lessonCount: number;
313
+ durationMinutes: number;
314
+ }
315
+ interface CurriculumLesson {
316
+ id: string;
317
+ title: string;
318
+ summary: string;
319
+ kind: Lesson["kind"];
320
+ durationMinutes: number;
321
+ preview: boolean;
322
+ required: boolean;
323
+ }
324
+ interface CurriculumModule {
325
+ id: string;
326
+ title: string;
327
+ description: string;
328
+ releaseDays: number;
329
+ unlockAt: string | null;
330
+ lessons: CurriculumLesson[];
331
+ }
332
+ interface CourseDetail extends CourseCard {
333
+ prerequisites: {
334
+ id: string;
335
+ title: string;
336
+ slug: string | null;
337
+ }[];
338
+ description: string;
339
+ outcomes: string[];
340
+ requirements: string[];
341
+ sequential: boolean;
342
+ prerequisiteCourseIds: string[];
343
+ enrollmentClosesAt: string | null;
344
+ accessDays: number;
345
+ certificateEnabled: boolean;
346
+ modules: CurriculumModule[];
347
+ }
348
+ interface PublicLesson extends Omit<Lesson, "quiz" | "contentSource"> {
349
+ quiz: (Omit<Quiz, "questions"> & {
350
+ questionCount: number;
351
+ }) | null;
352
+ }
353
+ interface Page<T> {
354
+ items: T[];
355
+ cursor?: string;
356
+ hasMore: boolean;
357
+ }
358
+ interface ProgressSummary {
359
+ completed: number;
360
+ total: number;
361
+ percent: number;
362
+ nextLessonId: string | null;
363
+ blockedLessonId: string | null;
364
+ availability: Record<string, LessonAvailability>;
365
+ }
366
+ interface LessonAvailability {
367
+ available: boolean;
368
+ code: string | null;
369
+ reason: string | null;
370
+ releaseAt: string | null;
371
+ }
372
+ interface LmsOptions {
373
+ basePath?: string;
374
+ loginPath?: string;
375
+ }
376
+ interface RouteEnvelope<T> {
377
+ success: boolean;
378
+ data?: T;
379
+ status?: number;
380
+ error?: {
381
+ code: string;
382
+ message: string;
383
+ };
384
+ }
385
+ //#endregion
386
+ export { AccessGrant, Acquisition, Actor, Answers, AssignmentSubmission, AuditRecord, Certificate, CertificateIndex, Cohort, CohortMembership, Course, CourseCard, CourseData, CourseDetail, CourseEdition, CourseModule, CourseRevision, CurriculumLesson, CurriculumModule, Discussion, Enrollment, LearnerPath, LearnerPreferences, LearningPath, Lesson, LessonAvailability, LessonProgress, LmsHealth, LmsOptions, LmsSettings, MigrationState, Notification, Page, PathEnrollment, Playback, ProgressSummary, PublicEnrollment, PublicLesson, PublicPath, PublicQuestion, PublicQuizAttempt, QuestionResult, Quiz, QuizAttempt, QuizQuestion, Review, RevisionSummary, RouteEnvelope, SavedCourse, Versioned };
387
+ //# sourceMappingURL=types.d.ts.map
package/dist/types.js ADDED
File without changes
package/package.json CHANGED
@@ -1,6 +1,85 @@
1
1
  {
2
2
  "name": "@anantagnanam/lms",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Courses, assessments, enrollment, progress, certificates and learning communities for EmDash CMS.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "homepage": "https://github.com/anantagnanam/anantagnanam-emdash-plugins#readme",
8
+ "bugs": "https://github.com/anantagnanam/anantagnanam-emdash-plugins/issues",
9
+ "keywords": [
10
+ "emdash",
11
+ "astro",
12
+ "lms",
13
+ "courses",
14
+ "education",
15
+ "anantagnanam"
16
+ ],
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/anantagnanam/anantagnanam-emdash-plugins.git",
20
+ "directory": "packages/lms"
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "astro",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js"
32
+ },
33
+ "./runtime": {
34
+ "types": "./dist/runtime.d.ts",
35
+ "import": "./dist/runtime.js"
36
+ },
37
+ "./admin": {
38
+ "types": "./dist/admin.d.ts",
39
+ "import": "./dist/admin.js"
40
+ },
41
+ "./astro": {
42
+ "types": "./dist/astro.d.ts",
43
+ "import": "./dist/astro.js"
44
+ },
45
+ "./server": {
46
+ "types": "./dist/server.d.ts",
47
+ "import": "./dist/server.js"
48
+ },
49
+ "./types": {
50
+ "types": "./dist/types.d.ts",
51
+ "import": "./dist/types.js"
52
+ },
53
+ "./schemas": {
54
+ "types": "./dist/schemas.d.ts",
55
+ "import": "./dist/schemas.js"
56
+ },
57
+ "./commerce": {
58
+ "types": "./dist/commerce.d.ts",
59
+ "import": "./dist/commerce.js"
60
+ },
61
+ "./components": "./astro/components/index.ts",
62
+ "./styles.css": "./astro/styles.css"
63
+ },
64
+ "scripts": {
65
+ "build": "tsdown",
66
+ "dev": "tsdown --watch --no-clean",
67
+ "typecheck": "tsc -p tsconfig.json",
68
+ "prepack": "npm run build"
69
+ },
70
+ "engines": {
71
+ "node": ">=22.16.0"
72
+ },
73
+ "peerDependencies": {
74
+ "emdash": ">=1.4.0 <2",
75
+ "astro": ">=7.0.0 <8",
76
+ "react": ">=19.0.0 <20"
77
+ },
78
+ "dependencies": {
79
+ "zod": "^4.6.7"
80
+ },
81
+ "publishConfig": {
82
+ "access": "public",
83
+ "registry": "https://registry.npmjs.org/"
84
+ }
85
+ }