@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,347 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/schemas.ts
4
+ const idSchema = z.string().min(1).max(128).regex(/^[a-zA-Z0-9_-]+$/, "Use letters, numbers, underscores or hyphens.").refine((value) => ![
5
+ "__proto__",
6
+ "constructor",
7
+ "prototype"
8
+ ].includes(value), "This identifier is reserved. Choose another ID.");
9
+ const keySchema = z.string().min(1).max(1024).regex(/^[a-zA-Z0-9_:.-]+$/);
10
+ const title = z.string().trim().min(1).max(200);
11
+ const text = z.string().max(5e4);
12
+ const timestamp = z.iso.datetime({ offset: true });
13
+ const safeUrlSchema = z.string().max(2048).refine((value) => {
14
+ if (/^\/(?!\/)[^\s\\]*$/.test(value)) return true;
15
+ try {
16
+ const url = new URL(value);
17
+ return url.protocol === "https:" && !url.username && !url.password;
18
+ } catch {
19
+ return false;
20
+ }
21
+ }, "Use an HTTPS URL or a path on this site.");
22
+ const resourceSchema = z.object({
23
+ id: idSchema,
24
+ title,
25
+ url: safeUrlSchema,
26
+ description: z.string().max(1e3).default("")
27
+ });
28
+ const optionSchema = z.object({
29
+ id: idSchema,
30
+ text: z.string().trim().min(1).max(2e3)
31
+ });
32
+ const questionSchema = z.object({
33
+ id: idSchema,
34
+ type: z.enum([
35
+ "single",
36
+ "multiple",
37
+ "true_false",
38
+ "short"
39
+ ]),
40
+ prompt: z.string().trim().min(1).max(5e3),
41
+ options: z.array(optionSchema).max(10).default([]),
42
+ correctAnswers: z.array(z.string().trim().min(1).max(500)).min(1).max(10),
43
+ points: z.number().int().min(1).max(100).default(1),
44
+ explanation: z.string().max(5e3).default("")
45
+ }).superRefine((question, ctx) => {
46
+ const optionIds = question.options.map((option) => option.id);
47
+ if (new Set(optionIds).size !== optionIds.length) ctx.addIssue({
48
+ code: "custom",
49
+ message: "Option IDs must be unique."
50
+ });
51
+ if (new Set(question.correctAnswers).size !== question.correctAnswers.length) ctx.addIssue({
52
+ code: "custom",
53
+ message: "Correct answers must be unique."
54
+ });
55
+ if (question.type !== "short") {
56
+ if (question.options.length < 2) ctx.addIssue({
57
+ code: "custom",
58
+ message: "Choice questions need at least two options."
59
+ });
60
+ if (question.correctAnswers.some((answer) => !optionIds.includes(answer))) ctx.addIssue({
61
+ code: "custom",
62
+ message: "Correct answers must refer to option IDs."
63
+ });
64
+ if (question.type !== "multiple" && question.correctAnswers.length !== 1) ctx.addIssue({
65
+ code: "custom",
66
+ message: "This question requires one correct answer."
67
+ });
68
+ if (question.type === "true_false" && (question.options.length !== 2 || !optionIds.includes("true") || !optionIds.includes("false"))) ctx.addIssue({
69
+ code: "custom",
70
+ message: "True/false options must have the IDs true and false."
71
+ });
72
+ }
73
+ });
74
+ const quizSchema = z.object({
75
+ questions: z.array(questionSchema).min(1).max(50),
76
+ passingPercent: z.number().int().min(1).max(100).default(70),
77
+ maxAttempts: z.number().int().min(1).max(20).default(3),
78
+ timeLimitMinutes: z.number().int().min(0).max(180).default(30),
79
+ randomizeQuestions: z.boolean().default(true),
80
+ randomizeOptions: z.boolean().default(false),
81
+ showFeedback: z.enum([
82
+ "after_pass",
83
+ "after_submit",
84
+ "never"
85
+ ]).default("after_pass")
86
+ }).refine((quiz) => new Set(quiz.questions.map((question) => question.id)).size === quiz.questions.length, "Question IDs must be unique.");
87
+ const assignmentSchema = z.object({
88
+ instructions: z.string().trim().min(1).max(2e4),
89
+ maxPoints: z.number().int().min(1).max(1e3).default(100),
90
+ passingPoints: z.number().int().min(1).max(1e3).default(60),
91
+ dueAt: timestamp.nullable().default(null),
92
+ allowResubmission: z.boolean().default(true)
93
+ }).refine((assignment) => assignment.passingPoints <= assignment.maxPoints, "Passing points cannot exceed maximum points.");
94
+ const lessonSchema = z.object({
95
+ id: idSchema,
96
+ title,
97
+ summary: z.string().max(2e3).default(""),
98
+ kind: z.enum([
99
+ "text",
100
+ "video",
101
+ "audio",
102
+ "quiz",
103
+ "assignment",
104
+ "live"
105
+ ]).default("text"),
106
+ body: text.default(""),
107
+ portableText: z.array(z.record(z.string(), z.unknown())).max(1e3).default([]),
108
+ contentSource: z.object({
109
+ collection: idSchema,
110
+ id: idSchema,
111
+ field: idSchema.default("content")
112
+ }).nullable().default(null),
113
+ mediaUrl: safeUrlSchema.nullable().default(null),
114
+ transcript: text.default(""),
115
+ captions: z.array(z.object({
116
+ src: safeUrlSchema,
117
+ language: z.string().regex(/^[a-zA-Z]{2,3}(?:-[a-zA-Z0-9]{2,8})*$/).max(35),
118
+ label: title
119
+ })).max(20).default([]),
120
+ liveStartsAt: timestamp.nullable().default(null),
121
+ durationMinutes: z.number().int().min(0).max(1440).default(10),
122
+ minStudySeconds: z.number().int().min(0).max(86400).default(0),
123
+ preview: z.boolean().default(false),
124
+ required: z.boolean().default(true),
125
+ resources: z.array(resourceSchema).max(30).default([]),
126
+ quiz: quizSchema.nullable().default(null),
127
+ assignment: assignmentSchema.nullable().default(null)
128
+ }).superRefine((lesson, ctx) => {
129
+ if (lesson.kind === "quiz" && !lesson.quiz) ctx.addIssue({
130
+ code: "custom",
131
+ message: "Quiz lessons need a quiz."
132
+ });
133
+ if (lesson.kind === "assignment" && !lesson.assignment) ctx.addIssue({
134
+ code: "custom",
135
+ message: "Assignment lessons need an assignment."
136
+ });
137
+ if ([
138
+ "video",
139
+ "audio",
140
+ "live"
141
+ ].includes(lesson.kind) && !lesson.mediaUrl) ctx.addIssue({
142
+ code: "custom",
143
+ message: "Media and live lessons need a URL."
144
+ });
145
+ if (lesson.kind === "live" && !lesson.liveStartsAt) ctx.addIssue({
146
+ code: "custom",
147
+ message: "Live lessons need a start time."
148
+ });
149
+ if (new Set(lesson.resources.map((resource) => resource.id)).size !== lesson.resources.length) ctx.addIssue({
150
+ code: "custom",
151
+ message: "Resource IDs must be unique."
152
+ });
153
+ });
154
+ const moduleSchema = z.object({
155
+ id: idSchema,
156
+ title,
157
+ description: z.string().max(2e3).default(""),
158
+ releaseDays: z.number().int().min(0).max(3650).default(0),
159
+ unlockAt: timestamp.nullable().default(null),
160
+ lessons: z.array(lessonSchema).max(100).default([])
161
+ });
162
+ const courseDataSchema = z.object({
163
+ slug: z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Use lowercase words separated by hyphens."),
164
+ title,
165
+ summary: z.string().trim().max(1e3).default(""),
166
+ description: text.default(""),
167
+ outcomes: z.array(z.string().trim().min(1).max(500)).max(30).default([]),
168
+ requirements: z.array(z.string().trim().min(1).max(500)).max(30).default([]),
169
+ category: z.string().trim().max(100).default(""),
170
+ tags: z.array(z.string().trim().min(1).max(60)).max(20).default([]),
171
+ language: z.string().trim().min(2).max(35).default("en"),
172
+ level: z.enum([
173
+ "beginner",
174
+ "intermediate",
175
+ "advanced",
176
+ "all"
177
+ ]).default("all"),
178
+ featuredImage: z.object({
179
+ id: z.string().max(128).default(""),
180
+ src: safeUrlSchema,
181
+ alt: z.string().max(500).default("")
182
+ }).nullable().default(null),
183
+ instructorName: z.string().trim().max(200).default(""),
184
+ instructorIds: z.array(idSchema).max(20).default([]),
185
+ status: z.enum([
186
+ "draft",
187
+ "published",
188
+ "archived"
189
+ ]).default("draft"),
190
+ enrollmentMode: z.enum([
191
+ "open",
192
+ "approval",
193
+ "invite"
194
+ ]).default("open"),
195
+ commerce: z.object({
196
+ accessModel: z.enum(["free", "paid"]).default("free"),
197
+ offerId: idSchema.nullable().default(null),
198
+ priceMinor: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).nullable().default(null),
199
+ currency: z.string().regex(/^[A-Z]{3}$/).default("INR")
200
+ }).default({
201
+ accessModel: "free",
202
+ offerId: null,
203
+ priceMinor: null,
204
+ currency: "INR"
205
+ }),
206
+ prerequisiteCourseIds: z.array(idSchema).max(20).default([]),
207
+ sequential: z.boolean().default(true),
208
+ enrollmentClosesAt: timestamp.nullable().default(null),
209
+ accessDays: z.number().int().min(0).max(3650).default(0),
210
+ certificateEnabled: z.boolean().default(true),
211
+ modules: z.array(moduleSchema).max(50).default([])
212
+ }).superRefine((course, ctx) => {
213
+ const allIds = course.modules.flatMap((module) => [module.id, ...module.lessons.map((lesson) => lesson.id)]);
214
+ if (new Set(allIds).size !== allIds.length) ctx.addIssue({
215
+ code: "custom",
216
+ message: "Module and lesson IDs must be unique across the course."
217
+ });
218
+ if (course.modules.flatMap((module) => module.lessons).length > 150) ctx.addIssue({
219
+ code: "custom",
220
+ message: "A course supports up to 150 lessons."
221
+ });
222
+ if (course.status === "published" && !course.modules.some((module) => module.lessons.some((lesson) => lesson.required))) ctx.addIssue({
223
+ code: "custom",
224
+ message: "Publish a course with at least one required lesson."
225
+ });
226
+ });
227
+ const courseSaveSchema = z.object({
228
+ id: idSchema.optional(),
229
+ expectedRevision: z.string().max(128).nullable().default(null),
230
+ data: courseDataSchema
231
+ });
232
+ const pageSchema = z.object({
233
+ cursor: z.string().max(4e3).optional(),
234
+ limit: z.coerce.number().int().min(1).max(100).default(24)
235
+ });
236
+ const catalogSchema = pageSchema.extend({
237
+ q: z.string().max(100).default(""),
238
+ category: z.string().max(100).default(""),
239
+ level: z.enum([
240
+ "beginner",
241
+ "intermediate",
242
+ "advanced",
243
+ "all"
244
+ ]).optional(),
245
+ language: z.string().max(35).optional()
246
+ });
247
+ const courseIdSchema = z.object({ courseId: idSchema });
248
+ const lessonIdSchema = courseIdSchema.extend({ lessonId: idSchema });
249
+ const answersSchema = z.record(idSchema, z.union([z.string().max(2e3), z.array(z.string().max(500)).max(10)]));
250
+ const quizSubmitSchema = lessonIdSchema.extend({
251
+ attemptId: idSchema,
252
+ answers: answersSchema,
253
+ expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).optional()
254
+ });
255
+ const quizDraftSchema = quizSubmitSchema.extend({ expectedDraftRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0) });
256
+ const assignmentSubmitSchema = lessonIdSchema.extend({
257
+ body: z.string().trim().min(1).max(2e4),
258
+ attachmentUrl: safeUrlSchema.nullable().default(null)
259
+ });
260
+ const enrollmentRequestSchema = courseIdSchema.extend({ cohortId: idSchema.optional() });
261
+ const enrollmentAdminSchema = courseIdSchema.extend({
262
+ userId: idSchema,
263
+ status: z.enum([
264
+ "active",
265
+ "rejected",
266
+ "suspended",
267
+ "cancelled"
268
+ ]),
269
+ reason: z.string().max(1e3).default(""),
270
+ cohortId: idSchema.nullable().optional(),
271
+ accessStartsAt: timestamp.nullable().optional(),
272
+ accessExpiresAt: timestamp.nullable().optional()
273
+ });
274
+ const gradeSchema = lessonIdSchema.extend({
275
+ userId: idSchema,
276
+ submissionId: idSchema,
277
+ points: z.number().int().min(0).max(1e3),
278
+ feedback: z.string().max(1e4).default("")
279
+ });
280
+ const discussionSchema = lessonIdSchema.extend({
281
+ body: z.string().trim().min(1).max(5e3),
282
+ parentId: idSchema.nullable().default(null)
283
+ });
284
+ const reviewSchema = courseIdSchema.extend({
285
+ rating: z.number().int().min(1).max(5),
286
+ body: z.string().trim().min(1).max(3e3)
287
+ });
288
+ const moderateSchema = z.object({
289
+ id: keySchema,
290
+ status: z.enum(["published", "hidden"]),
291
+ expectedRevision: z.string().min(1).max(128)
292
+ });
293
+ const cohortDataSchema = z.object({
294
+ title,
295
+ courseIds: z.array(idSchema).min(1).max(20),
296
+ memberIds: z.array(idSchema).max(1e3).default([]),
297
+ startsAt: timestamp.nullable().default(null),
298
+ endsAt: timestamp.nullable().default(null)
299
+ }).refine((cohort) => !cohort.startsAt || !cohort.endsAt || Date.parse(cohort.endsAt) > Date.parse(cohort.startsAt), "Cohort end must follow its start.").refine((cohort) => new Set(cohort.memberIds).size === cohort.memberIds.length, "Cohort members must be unique.").refine((cohort) => new Set(cohort.courseIds).size === cohort.courseIds.length, "Cohort courses must be unique.");
300
+ const cohortSaveSchema = z.object({
301
+ id: idSchema.optional(),
302
+ expectedRevision: z.string().max(128).nullable().default(null),
303
+ data: cohortDataSchema
304
+ });
305
+ const settingsSchema = z.object({
306
+ academyTitle: title.default("Ananta Gnanam Academy"),
307
+ academyDescription: z.string().max(2e3).default("Build knowledge, one lesson at a time."),
308
+ issuerName: title.default("Ananta Gnanam"),
309
+ moderateDiscussions: z.boolean().default(true),
310
+ moderateReviews: z.boolean().default(true),
311
+ emailNotifications: z.boolean().default(false),
312
+ reminderDays: z.number().int().min(0).max(90).default(7)
313
+ });
314
+ const certificateActionSchema = courseIdSchema.extend({ shared: z.boolean() });
315
+ const certificateRevokeSchema = courseIdSchema.extend({
316
+ userId: idSchema,
317
+ reason: z.string().trim().min(1).max(1e3)
318
+ });
319
+ const noteSchema = lessonIdSchema.extend({ note: z.string().max(1e4) });
320
+ const preferencesSchema = z.object({
321
+ emailNotifications: z.boolean().default(true),
322
+ weeklyGoalLessons: z.number().int().min(0).max(100).default(3)
323
+ });
324
+ const playbackSchema = lessonIdSchema.extend({
325
+ positionSeconds: z.number().finite().min(0).max(86400),
326
+ playbackRate: z.number().min(.25).max(3),
327
+ expectedRevision: z.number().int().min(0).max(Number.MAX_SAFE_INTEGER)
328
+ });
329
+ const pathDataSchema = z.object({
330
+ title,
331
+ description: z.string().max(5e3).default(""),
332
+ courseIds: z.array(idSchema).min(1).max(30).refine((ids) => new Set(ids).size === ids.length, "Courses must be unique."),
333
+ status: z.enum([
334
+ "draft",
335
+ "published",
336
+ "archived"
337
+ ]).default("draft")
338
+ });
339
+ const pathSaveSchema = z.object({
340
+ id: idSchema.optional(),
341
+ expectedRevision: z.string().max(128).nullable().default(null),
342
+ data: pathDataSchema
343
+ });
344
+
345
+ //#endregion
346
+ export { answersSchema, 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, safeUrlSchema, settingsSchema };
347
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +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 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});\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\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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"}
@@ -0,0 +1,40 @@
1
+ import { CourseDetail, PublicLesson } from "./types.js";
2
+
3
+ //#region src/errors.d.ts
4
+ declare class LmsError extends Error {
5
+ readonly code: string;
6
+ readonly status: number;
7
+ constructor(code: string, message: string, status?: number);
8
+ }
9
+ //#endregion
10
+ //#region src/server.d.ts
11
+ interface RuntimeLocals {
12
+ user?: {
13
+ id: string;
14
+ email: string;
15
+ name: string | null;
16
+ role: number;
17
+ createdAt: Date | string;
18
+ };
19
+ emdash?: {
20
+ handlePublicPluginApiRoute?: (pluginId: string, method: string, path: string, request: Request) => Promise<unknown>;
21
+ handlePluginApiRoute?: (pluginId: string, method: string, path: string, request: Request, user?: RuntimeLocals["user"] | null) => Promise<unknown>;
22
+ };
23
+ }
24
+ declare function lmsPublic<T>(locals: RuntimeLocals, route: string, input: Record<string, unknown>, origin: string): Promise<T>;
25
+ declare function lmsLearner<T>(locals: RuntimeLocals, route: string, input: Record<string, unknown>, origin: string): Promise<T>;
26
+ declare function loginUrl(loginPath: string, returnTo: string): string;
27
+ /** A fixed private read route; authorization remains at the EmDash runtime boundary. */
28
+ declare function lmsAuthorLessonPreview(locals: RuntimeLocals, input: {
29
+ courseId: string;
30
+ lessonId: string;
31
+ }, origin: string): Promise<{
32
+ course: CourseDetail;
33
+ lesson: PublicLesson;
34
+ }>;
35
+ declare function courseUrl(basePath: string, slug: string): string;
36
+ declare function lessonUrl(basePath: string, slug: string, lessonId: string): string;
37
+ declare function certificateUrl(basePath: string, id: string): string;
38
+ //#endregion
39
+ export { LmsError, certificateUrl, courseUrl, lessonUrl, lmsAuthorLessonPreview, lmsLearner, lmsPublic, loginUrl };
40
+ //# sourceMappingURL=server.d.ts.map
package/dist/server.js ADDED
@@ -0,0 +1,65 @@
1
+ import { r as PLUGIN_ID } from "./constants-Cnx7k82Z.js";
2
+ import { t as LmsError } from "./errors-ChzJS9al.js";
3
+
4
+ //#region src/server.ts
5
+ function requestUrl(route, input, origin) {
6
+ const url = new URL(`/_emdash/api/plugins/${PLUGIN_ID}/${route}`, origin);
7
+ for (const [key, value] of Object.entries(input)) if (value !== void 0 && value !== null && value !== "") url.searchParams.set(key, String(value));
8
+ return url;
9
+ }
10
+ function unwrap(input) {
11
+ const result = input;
12
+ if (!result?.success) throw new LmsError(result?.error?.code ?? "LMS_UNAVAILABLE", result?.error?.message ?? "The learning service is unavailable.", result?.status ?? 503);
13
+ return result.data;
14
+ }
15
+ async function lmsPublic(locals, route, input, origin) {
16
+ const dispatch = locals.emdash?.handlePublicPluginApiRoute;
17
+ if (!dispatch) throw new LmsError("LMS_UNAVAILABLE", "The learning service is unavailable.", 503);
18
+ return unwrap(await dispatch(PLUGIN_ID, "GET", route, new Request(requestUrl(route, input, origin))));
19
+ }
20
+ const READ_ROUTES = new Set([
21
+ "learner/paths",
22
+ "learner/saved",
23
+ "learner/preferences",
24
+ "learner/dashboard",
25
+ "learner/course",
26
+ "learner/course-by-slug",
27
+ "learner/lesson",
28
+ "learner/certificate",
29
+ "learner/certificate-by-id",
30
+ "learner/cohort",
31
+ "learner/notifications"
32
+ ]);
33
+ async function lmsLearner(locals, route, input, origin) {
34
+ if (!locals.user || locals.user.role < 10) throw new LmsError("UNAUTHORIZED", "Sign in to continue.", 401);
35
+ if (!READ_ROUTES.has(route)) throw new LmsError("FORBIDDEN", "This route is not available to the learner renderer.", 403);
36
+ const dispatch = locals.emdash?.handlePluginApiRoute;
37
+ if (!dispatch) throw new LmsError("LMS_UNAVAILABLE", "The learning service is unavailable.", 503);
38
+ return unwrap(await dispatch(PLUGIN_ID, "GET", route, new Request(requestUrl(route, input, origin)), locals.user));
39
+ }
40
+ function loginUrl(loginPath, returnTo) {
41
+ const url = new URL(loginPath, "https://lms.invalid");
42
+ url.searchParams.set("redirect", returnTo);
43
+ return `${url.pathname}${url.search}${url.hash}`;
44
+ }
45
+ /** A fixed private read route; authorization remains at the EmDash runtime boundary. */
46
+ async function lmsAuthorLessonPreview(locals, input, origin) {
47
+ if (!locals.user) throw new LmsError("UNAUTHORIZED", "Sign in to preview this lesson.", 401);
48
+ const dispatch = locals.emdash?.handlePluginApiRoute;
49
+ if (!dispatch) throw new LmsError("LMS_UNAVAILABLE", "The learning service is unavailable.", 503);
50
+ const route = "admin/lesson/preview";
51
+ return unwrap(await dispatch(PLUGIN_ID, "GET", route, new Request(requestUrl(route, input, origin)), locals.user));
52
+ }
53
+ function courseUrl(basePath, slug) {
54
+ return `${basePath}/courses/${encodeURIComponent(slug)}`;
55
+ }
56
+ function lessonUrl(basePath, slug, lessonId) {
57
+ return `${courseUrl(basePath, slug)}/lessons/${encodeURIComponent(lessonId)}`;
58
+ }
59
+ function certificateUrl(basePath, id) {
60
+ return `${basePath}/certificates/${encodeURIComponent(id)}`;
61
+ }
62
+
63
+ //#endregion
64
+ export { LmsError, certificateUrl, courseUrl, lessonUrl, lmsAuthorLessonPreview, lmsLearner, lmsPublic, loginUrl };
65
+ //# sourceMappingURL=server.js.map
@@ -0,0 +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 { 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/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":";;;;AAuBA,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;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"}