@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.
- package/LICENSE +21 -0
- package/README.md +98 -2
- package/astro/client.ts +355 -0
- package/astro/components/CertificateCard.astro +83 -0
- package/astro/components/CourseCard.astro +61 -0
- package/astro/components/CourseCatalog.astro +96 -0
- package/astro/components/CourseOverview.astro +308 -0
- package/astro/components/LearnerDashboard.astro +127 -0
- package/astro/components/LearningShell.astro +37 -0
- package/astro/components/LessonAvailabilityNote.astro +26 -0
- package/astro/components/LessonContent.astro +53 -0
- package/astro/components/LessonPlayer.astro +302 -0
- package/astro/components/MediaPlayer.astro +111 -0
- package/astro/components/index.ts +7 -0
- package/astro/layouts/AcademyLayout.astro +84 -0
- package/astro/media-player.ts +99 -0
- package/astro/pages/author-preview.astro +71 -0
- package/astro/pages/certificate.astro +57 -0
- package/astro/pages/cohort.astro +102 -0
- package/astro/pages/course.astro +90 -0
- package/astro/pages/dashboard.astro +34 -0
- package/astro/pages/index.astro +40 -0
- package/astro/pages/lesson.astro +103 -0
- package/astro/pages/library.astro +173 -0
- package/astro/pages/paths.astro +73 -0
- package/astro/pages/teach.astro +15 -0
- package/astro/quiz-drafts.ts +87 -0
- package/astro/quiz-player.ts +362 -0
- package/astro/styles.css +1300 -0
- package/dist/admin.d.ts +34 -0
- package/dist/admin.js +3231 -0
- package/dist/admin.js.map +1 -0
- package/dist/astro.d.ts +11 -0
- package/dist/astro.js +52 -0
- package/dist/astro.js.map +1 -0
- package/dist/commerce.d.ts +72 -0
- package/dist/commerce.js +0 -0
- package/dist/config-BX3beTpM.js +15 -0
- package/dist/config-BX3beTpM.js.map +1 -0
- package/dist/constants-Cnx7k82Z.js +161 -0
- package/dist/constants-Cnx7k82Z.js.map +1 -0
- package/dist/csv-DKq_4OWU.js +55 -0
- package/dist/csv-DKq_4OWU.js.map +1 -0
- package/dist/errors-ChzJS9al.js +16 -0
- package/dist/errors-ChzJS9al.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +773 -0
- package/dist/runtime.js +2840 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schemas.d.ts +651 -0
- package/dist/schemas.js +347 -0
- package/dist/schemas.js.map +1 -0
- package/dist/server.d.ts +40 -0
- package/dist/server.js +65 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +387 -0
- package/dist/types.js +0 -0
- package/package.json +83 -4
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
//#region src/commerce.d.ts
|
|
2
|
+
/** Provider contracts reserved for a later commerce module. No payments run in v0.1. */
|
|
3
|
+
interface Money {
|
|
4
|
+
amountMinor: number;
|
|
5
|
+
currency: string;
|
|
6
|
+
}
|
|
7
|
+
interface CheckoutCommand {
|
|
8
|
+
orderId: string;
|
|
9
|
+
learnerId: string;
|
|
10
|
+
offerId: string;
|
|
11
|
+
courseId: string;
|
|
12
|
+
cohortId: string | null;
|
|
13
|
+
money: Money;
|
|
14
|
+
returnUrl: string;
|
|
15
|
+
idempotencyKey: string;
|
|
16
|
+
}
|
|
17
|
+
interface CheckoutSession {
|
|
18
|
+
providerId: string;
|
|
19
|
+
providerSessionId: string;
|
|
20
|
+
checkoutUrl: string;
|
|
21
|
+
expiresAt: string | null;
|
|
22
|
+
}
|
|
23
|
+
interface VerifiedPaymentEvent {
|
|
24
|
+
id: string;
|
|
25
|
+
providerId: string;
|
|
26
|
+
orderId: string;
|
|
27
|
+
providerPaymentId: string;
|
|
28
|
+
type: "payment.captured" | "payment.failed" | "payment.refunded" | "payment.partially_refunded";
|
|
29
|
+
money: Money;
|
|
30
|
+
occurredAt: string;
|
|
31
|
+
}
|
|
32
|
+
interface PaymentProvider {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
createCheckout(command: CheckoutCommand): Promise<CheckoutSession>;
|
|
35
|
+
verifyWebhook(input: {
|
|
36
|
+
rawBody: Uint8Array;
|
|
37
|
+
headers: Headers;
|
|
38
|
+
}): Promise<VerifiedPaymentEvent>;
|
|
39
|
+
refund(input: {
|
|
40
|
+
orderId: string;
|
|
41
|
+
providerPaymentId: string;
|
|
42
|
+
money: Money;
|
|
43
|
+
idempotencyKey: string;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
providerRefundId: string;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
interface Order {
|
|
49
|
+
id: string;
|
|
50
|
+
learnerId: string;
|
|
51
|
+
courseId: string;
|
|
52
|
+
cohortId: string | null;
|
|
53
|
+
offerId: string;
|
|
54
|
+
money: Money;
|
|
55
|
+
status: "pending" | "paid" | "failed" | "partially_refunded" | "refunded" | "cancelled";
|
|
56
|
+
providerId: string | null;
|
|
57
|
+
providerSessionId: string | null;
|
|
58
|
+
providerPaymentId: string | null;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
paidAt: string | null;
|
|
61
|
+
}
|
|
62
|
+
interface AccessGrantCommand {
|
|
63
|
+
enrollmentId: string;
|
|
64
|
+
orderId: string;
|
|
65
|
+
source: "purchase";
|
|
66
|
+
startsAt: string | null;
|
|
67
|
+
expiresAt: string | null;
|
|
68
|
+
eventId: string;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { AccessGrantCommand, CheckoutCommand, CheckoutSession, Money, Order, PaymentProvider, VerifiedPaymentEvent };
|
|
72
|
+
//# sourceMappingURL=commerce.d.ts.map
|
package/dist/commerce.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/config.ts
|
|
2
|
+
function normalizeLmsOptions(options = {}) {
|
|
3
|
+
const basePath = (options.basePath ?? "/academy").replace(/\/+$/, "");
|
|
4
|
+
const loginPath = options.loginPath ?? "/login";
|
|
5
|
+
if (basePath.length > 250 || !/^(?:\/[a-zA-Z0-9_-]+)+$/.test(basePath)) throw new Error("LMS basePath must be a non-root site path such as /academy.");
|
|
6
|
+
if (loginPath.length > 2048 || !/^\/(?!\/)[^\s\\]*$/.test(loginPath)) throw new Error("LMS loginPath must be a path on this site.");
|
|
7
|
+
return {
|
|
8
|
+
basePath,
|
|
9
|
+
loginPath
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { normalizeLmsOptions as t };
|
|
15
|
+
//# sourceMappingURL=config-BX3beTpM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-BX3beTpM.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import type { LmsOptions } from \"./types.js\";\n\nexport function normalizeLmsOptions(options: LmsOptions = {}): Required<LmsOptions> {\n const basePath = (options.basePath ?? \"/academy\").replace(/\\/+$/, \"\");\n const loginPath = options.loginPath ?? \"/login\";\n if (basePath.length > 250 || !/^(?:\\/[a-zA-Z0-9_-]+)+$/.test(basePath))\n throw new Error(\"LMS basePath must be a non-root site path such as /academy.\");\n if (loginPath.length > 2048 || !/^\\/(?!\\/)[^\\s\\\\]*$/.test(loginPath))\n throw new Error(\"LMS loginPath must be a path on this site.\");\n return { basePath, loginPath };\n}\n"],"mappings":";AAEA,SAAgB,oBAAoB,UAAsB,EAAE,EAAwB;CAClF,MAAM,YAAY,QAAQ,YAAY,YAAY,QAAQ,QAAQ,GAAG;CACrE,MAAM,YAAY,QAAQ,aAAa;AACvC,KAAI,SAAS,SAAS,OAAO,CAAC,0BAA0B,KAAK,SAAS,CACpE,OAAM,IAAI,MAAM,8DAA8D;AAChF,KAAI,UAAU,SAAS,QAAQ,CAAC,qBAAqB,KAAK,UAAU,CAClE,OAAM,IAAI,MAAM,6CAA6C;AAC/D,QAAO;EAAE;EAAU;EAAW"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//#region src/constants.ts
|
|
2
|
+
const PLUGIN_ID = "anantagnanam-lms";
|
|
3
|
+
const PLUGIN_VERSION = "0.2.0";
|
|
4
|
+
const API_BASE = `/_emdash/api/plugins/${PLUGIN_ID}`;
|
|
5
|
+
const MAX_DOCUMENT_BYTES = 95e4;
|
|
6
|
+
const storage = {
|
|
7
|
+
courses: {
|
|
8
|
+
indexes: [
|
|
9
|
+
"status",
|
|
10
|
+
"title",
|
|
11
|
+
"searchTitle",
|
|
12
|
+
"category",
|
|
13
|
+
"level",
|
|
14
|
+
"language",
|
|
15
|
+
"updatedAt",
|
|
16
|
+
"createdBy",
|
|
17
|
+
"createdAt"
|
|
18
|
+
],
|
|
19
|
+
uniqueIndexes: ["slug"]
|
|
20
|
+
},
|
|
21
|
+
course_revisions: { indexes: ["courseId", "createdAt"] },
|
|
22
|
+
course_editions: { indexes: ["courseId", "createdAt"] },
|
|
23
|
+
migrations: { indexes: ["phase"] },
|
|
24
|
+
preferences: { indexes: [] },
|
|
25
|
+
saved_courses: { indexes: [
|
|
26
|
+
"userId",
|
|
27
|
+
"saved",
|
|
28
|
+
"updatedAt"
|
|
29
|
+
] },
|
|
30
|
+
learning_paths: { indexes: ["status", "updatedAt"] },
|
|
31
|
+
path_enrollments: { indexes: [
|
|
32
|
+
"userId",
|
|
33
|
+
"pathId",
|
|
34
|
+
"joinedAt"
|
|
35
|
+
] },
|
|
36
|
+
enrollments: { indexes: [
|
|
37
|
+
"userId",
|
|
38
|
+
"courseId",
|
|
39
|
+
"status",
|
|
40
|
+
"accessStatus",
|
|
41
|
+
"accessSource",
|
|
42
|
+
"enrolledAt",
|
|
43
|
+
"completedAt",
|
|
44
|
+
"lastActivityAt",
|
|
45
|
+
"cohortId",
|
|
46
|
+
["courseId", "status"],
|
|
47
|
+
["userId", "status"]
|
|
48
|
+
] },
|
|
49
|
+
certificates: { indexes: ["userId", "courseId"] },
|
|
50
|
+
discussions: { indexes: [
|
|
51
|
+
"courseId",
|
|
52
|
+
"lessonId",
|
|
53
|
+
"authorId",
|
|
54
|
+
"status",
|
|
55
|
+
"createdAt",
|
|
56
|
+
"parentId",
|
|
57
|
+
["courseId", "createdAt"]
|
|
58
|
+
] },
|
|
59
|
+
reviews: { indexes: [
|
|
60
|
+
"courseId",
|
|
61
|
+
"userId",
|
|
62
|
+
"status",
|
|
63
|
+
"createdAt"
|
|
64
|
+
] },
|
|
65
|
+
cohorts: { indexes: [
|
|
66
|
+
"title",
|
|
67
|
+
"createdAt",
|
|
68
|
+
"createdBy"
|
|
69
|
+
] },
|
|
70
|
+
cohort_enrollments: { indexes: [
|
|
71
|
+
"cohortId",
|
|
72
|
+
"userId",
|
|
73
|
+
"status",
|
|
74
|
+
"requestedAt"
|
|
75
|
+
] },
|
|
76
|
+
notifications: { indexes: [
|
|
77
|
+
"userId",
|
|
78
|
+
"read",
|
|
79
|
+
"createdAt",
|
|
80
|
+
"emailStatus",
|
|
81
|
+
"claimedAt"
|
|
82
|
+
] },
|
|
83
|
+
audit: { indexes: [
|
|
84
|
+
"actorId",
|
|
85
|
+
"action",
|
|
86
|
+
"resourceId",
|
|
87
|
+
"createdAt"
|
|
88
|
+
] }
|
|
89
|
+
};
|
|
90
|
+
const adminPages = [
|
|
91
|
+
{
|
|
92
|
+
path: "/",
|
|
93
|
+
label: "Learning overview",
|
|
94
|
+
icon: "graduation-cap",
|
|
95
|
+
group: "Learning"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
path: "/courses",
|
|
99
|
+
label: "Courses",
|
|
100
|
+
icon: "books",
|
|
101
|
+
group: "Learning"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
path: "/learners",
|
|
105
|
+
label: "Enrollments",
|
|
106
|
+
icon: "users",
|
|
107
|
+
group: "Learning"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
path: "/assignments",
|
|
111
|
+
label: "Assignments",
|
|
112
|
+
icon: "exam",
|
|
113
|
+
group: "Learning"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
path: "/community",
|
|
117
|
+
label: "Community",
|
|
118
|
+
icon: "chats",
|
|
119
|
+
group: "Learning"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
path: "/cohorts",
|
|
123
|
+
label: "Cohorts",
|
|
124
|
+
icon: "users-three",
|
|
125
|
+
group: "Learning"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
path: "/paths",
|
|
129
|
+
label: "Learning paths",
|
|
130
|
+
icon: "books",
|
|
131
|
+
group: "Learning"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
path: "/reports",
|
|
135
|
+
label: "Reports",
|
|
136
|
+
icon: "chart-bar",
|
|
137
|
+
group: "Learning"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
path: "/notifications",
|
|
141
|
+
label: "Notifications",
|
|
142
|
+
icon: "bell",
|
|
143
|
+
group: "Learning"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
path: "/audit",
|
|
147
|
+
label: "Audit history",
|
|
148
|
+
icon: "clock-counter-clockwise",
|
|
149
|
+
group: "Learning"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
path: "/settings",
|
|
153
|
+
label: "LMS settings",
|
|
154
|
+
icon: "gear",
|
|
155
|
+
group: "Learning"
|
|
156
|
+
}
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
//#endregion
|
|
160
|
+
export { adminPages as a, PLUGIN_VERSION as i, MAX_DOCUMENT_BYTES as n, storage as o, PLUGIN_ID as r, API_BASE as t };
|
|
161
|
+
//# sourceMappingURL=constants-Cnx7k82Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-Cnx7k82Z.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["export const PLUGIN_ID = \"anantagnanam-lms\";\nexport const PLUGIN_VERSION = \"0.2.0\";\nexport const API_BASE = `/_emdash/api/plugins/${PLUGIN_ID}`;\nexport const MAX_DOCUMENT_BYTES = 950_000;\n\nimport type { PluginStorageConfig } from \"emdash\";\n\nexport const storage = {\n courses: {\n indexes: [\n \"status\",\n \"title\",\n \"searchTitle\",\n \"category\",\n \"level\",\n \"language\",\n \"updatedAt\",\n \"createdBy\",\n \"createdAt\",\n ],\n uniqueIndexes: [\"slug\"],\n },\n course_revisions: { indexes: [\"courseId\", \"createdAt\"] },\n course_editions: { indexes: [\"courseId\", \"createdAt\"] },\n migrations: { indexes: [\"phase\"] },\n preferences: { indexes: [] },\n saved_courses: { indexes: [\"userId\", \"saved\", \"updatedAt\"] },\n learning_paths: { indexes: [\"status\", \"updatedAt\"] },\n path_enrollments: { indexes: [\"userId\", \"pathId\", \"joinedAt\"] },\n enrollments: {\n indexes: [\n \"userId\",\n \"courseId\",\n \"status\",\n \"accessStatus\",\n \"accessSource\",\n \"enrolledAt\",\n \"completedAt\",\n \"lastActivityAt\",\n \"cohortId\",\n [\"courseId\", \"status\"],\n [\"userId\", \"status\"],\n ],\n },\n certificates: { indexes: [\"userId\", \"courseId\"] },\n discussions: {\n indexes: [\n \"courseId\",\n \"lessonId\",\n \"authorId\",\n \"status\",\n \"createdAt\",\n \"parentId\",\n [\"courseId\", \"createdAt\"],\n ],\n },\n reviews: { indexes: [\"courseId\", \"userId\", \"status\", \"createdAt\"] },\n cohorts: { indexes: [\"title\", \"createdAt\", \"createdBy\"] },\n cohort_enrollments: { indexes: [\"cohortId\", \"userId\", \"status\", \"requestedAt\"] },\n notifications: { indexes: [\"userId\", \"read\", \"createdAt\", \"emailStatus\", \"claimedAt\"] },\n audit: { indexes: [\"actorId\", \"action\", \"resourceId\", \"createdAt\"] },\n} satisfies PluginStorageConfig;\n\nexport const adminPages = [\n { path: \"/\", label: \"Learning overview\", icon: \"graduation-cap\", group: \"Learning\" },\n { path: \"/courses\", label: \"Courses\", icon: \"books\", group: \"Learning\" },\n { path: \"/learners\", label: \"Enrollments\", icon: \"users\", group: \"Learning\" },\n { path: \"/assignments\", label: \"Assignments\", icon: \"exam\", group: \"Learning\" },\n { path: \"/community\", label: \"Community\", icon: \"chats\", group: \"Learning\" },\n { path: \"/cohorts\", label: \"Cohorts\", icon: \"users-three\", group: \"Learning\" },\n { path: \"/paths\", label: \"Learning paths\", icon: \"books\", group: \"Learning\" },\n { path: \"/reports\", label: \"Reports\", icon: \"chart-bar\", group: \"Learning\" },\n { path: \"/notifications\", label: \"Notifications\", icon: \"bell\", group: \"Learning\" },\n { path: \"/audit\", label: \"Audit history\", icon: \"clock-counter-clockwise\", group: \"Learning\" },\n { path: \"/settings\", label: \"LMS settings\", icon: \"gear\", group: \"Learning\" },\n];\n"],"mappings":";AAAA,MAAa,YAAY;AACzB,MAAa,iBAAiB;AAC9B,MAAa,WAAW,wBAAwB;AAChD,MAAa,qBAAqB;AAIlC,MAAa,UAAU;CACrB,SAAS;EACP,SAAS;GACP;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACD,eAAe,CAAC,OAAO;EACxB;CACD,kBAAkB,EAAE,SAAS,CAAC,YAAY,YAAY,EAAE;CACxD,iBAAiB,EAAE,SAAS,CAAC,YAAY,YAAY,EAAE;CACvD,YAAY,EAAE,SAAS,CAAC,QAAQ,EAAE;CAClC,aAAa,EAAE,SAAS,EAAE,EAAE;CAC5B,eAAe,EAAE,SAAS;EAAC;EAAU;EAAS;EAAY,EAAE;CAC5D,gBAAgB,EAAE,SAAS,CAAC,UAAU,YAAY,EAAE;CACpD,kBAAkB,EAAE,SAAS;EAAC;EAAU;EAAU;EAAW,EAAE;CAC/D,aAAa,EACX,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,YAAY,SAAS;EACtB,CAAC,UAAU,SAAS;EACrB,EACF;CACD,cAAc,EAAE,SAAS,CAAC,UAAU,WAAW,EAAE;CACjD,aAAa,EACX,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,YAAY,YAAY;EAC1B,EACF;CACD,SAAS,EAAE,SAAS;EAAC;EAAY;EAAU;EAAU;EAAY,EAAE;CACnE,SAAS,EAAE,SAAS;EAAC;EAAS;EAAa;EAAY,EAAE;CACzD,oBAAoB,EAAE,SAAS;EAAC;EAAY;EAAU;EAAU;EAAc,EAAE;CAChF,eAAe,EAAE,SAAS;EAAC;EAAU;EAAQ;EAAa;EAAe;EAAY,EAAE;CACvF,OAAO,EAAE,SAAS;EAAC;EAAW;EAAU;EAAc;EAAY,EAAE;CACrE;AAED,MAAa,aAAa;CACxB;EAAE,MAAM;EAAK,OAAO;EAAqB,MAAM;EAAkB,OAAO;EAAY;CACpF;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAS,OAAO;EAAY;CACxE;EAAE,MAAM;EAAa,OAAO;EAAe,MAAM;EAAS,OAAO;EAAY;CAC7E;EAAE,MAAM;EAAgB,OAAO;EAAe,MAAM;EAAQ,OAAO;EAAY;CAC/E;EAAE,MAAM;EAAc,OAAO;EAAa,MAAM;EAAS,OAAO;EAAY;CAC5E;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAe,OAAO;EAAY;CAC9E;EAAE,MAAM;EAAU,OAAO;EAAkB,MAAM;EAAS,OAAO;EAAY;CAC7E;EAAE,MAAM;EAAY,OAAO;EAAW,MAAM;EAAa,OAAO;EAAY;CAC5E;EAAE,MAAM;EAAkB,OAAO;EAAiB,MAAM;EAAQ,OAAO;EAAY;CACnF;EAAE,MAAM;EAAU,OAAO;EAAiB,MAAM;EAA2B,OAAO;EAAY;CAC9F;EAAE,MAAM;EAAa,OAAO;EAAgB,MAAM;EAAQ,OAAO;EAAY;CAC9E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/csv.ts
|
|
2
|
+
function csvLine(values) {
|
|
3
|
+
return values.map((value) => {
|
|
4
|
+
const text = String(value ?? "");
|
|
5
|
+
return `"${(/^[=+\-@]/.test(text.trimStart()) || /^[\t\r\n]/.test(text) ? "'" + text : text).replaceAll("\"", "\"\"")}"`;
|
|
6
|
+
}).join(",");
|
|
7
|
+
}
|
|
8
|
+
const enrollmentCsvHeader = csvLine([
|
|
9
|
+
"Learner",
|
|
10
|
+
"Email",
|
|
11
|
+
"Course",
|
|
12
|
+
"Status",
|
|
13
|
+
"Access decision",
|
|
14
|
+
"Effective access",
|
|
15
|
+
"Access source",
|
|
16
|
+
"Progress %",
|
|
17
|
+
"Enrolled",
|
|
18
|
+
"Completed",
|
|
19
|
+
"Last activity",
|
|
20
|
+
"Access starts",
|
|
21
|
+
"Access expires",
|
|
22
|
+
"Order ID",
|
|
23
|
+
"Offer ID",
|
|
24
|
+
"Payment status",
|
|
25
|
+
"Amount minor",
|
|
26
|
+
"Currency",
|
|
27
|
+
"Provider"
|
|
28
|
+
]);
|
|
29
|
+
function enrollmentCsvLines(rows) {
|
|
30
|
+
return rows.map((row) => csvLine([
|
|
31
|
+
row.learnerName,
|
|
32
|
+
row.learnerEmail,
|
|
33
|
+
row.courseTitle,
|
|
34
|
+
row.status,
|
|
35
|
+
row.accessStatus,
|
|
36
|
+
row.effectiveAccess,
|
|
37
|
+
row.accessSource,
|
|
38
|
+
row.progressSummary?.percent ?? 0,
|
|
39
|
+
row.enrolledAt,
|
|
40
|
+
row.completedAt,
|
|
41
|
+
row.lastActivityAt,
|
|
42
|
+
row.accessStartsAt,
|
|
43
|
+
row.accessExpiresAt,
|
|
44
|
+
row.acquisition.orderId,
|
|
45
|
+
row.acquisition.offerId,
|
|
46
|
+
row.acquisition.paymentStatus,
|
|
47
|
+
row.acquisition.amountMinor,
|
|
48
|
+
row.acquisition.currency,
|
|
49
|
+
row.acquisition.providerId
|
|
50
|
+
]));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { enrollmentCsvLines as n, enrollmentCsvHeader as t };
|
|
55
|
+
//# sourceMappingURL=csv-DKq_4OWU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csv-DKq_4OWU.js","names":[],"sources":["../src/csv.ts"],"sourcesContent":["import type { PublicEnrollment } from \"./types.js\";\n\ntype EnrollmentCsvRow = Pick<\n PublicEnrollment,\n | \"learnerName\"\n | \"status\"\n | \"accessStatus\"\n | \"effectiveAccess\"\n | \"accessSource\"\n | \"enrolledAt\"\n | \"completedAt\"\n | \"lastActivityAt\"\n | \"accessStartsAt\"\n | \"accessExpiresAt\"\n | \"acquisition\"\n> & { learnerEmail: string; courseTitle: string; progressSummary: { percent: number } | null };\n\nfunction csvLine(values: unknown[]): string {\n return values\n .map((value) => {\n const text = String(value ?? \"\");\n const safe = /^[=+\\-@]/.test(text.trimStart()) || /^[\\t\\r\\n]/.test(text) ? \"'\" + text : text;\n return `\"${safe.replaceAll('\"', '\"\"')}\"`;\n })\n .join(\",\");\n}\n\nexport const enrollmentCsvHeader = csvLine([\n \"Learner\",\n \"Email\",\n \"Course\",\n \"Status\",\n \"Access decision\",\n \"Effective access\",\n \"Access source\",\n \"Progress %\",\n \"Enrolled\",\n \"Completed\",\n \"Last activity\",\n \"Access starts\",\n \"Access expires\",\n \"Order ID\",\n \"Offer ID\",\n \"Payment status\",\n \"Amount minor\",\n \"Currency\",\n \"Provider\",\n]);\n\nexport function enrollmentCsvLines(rows: EnrollmentCsvRow[]): string[] {\n return rows.map((row) =>\n csvLine([\n row.learnerName,\n row.learnerEmail,\n row.courseTitle,\n row.status,\n row.accessStatus,\n row.effectiveAccess,\n row.accessSource,\n row.progressSummary?.percent ?? 0,\n row.enrolledAt,\n row.completedAt,\n row.lastActivityAt,\n row.accessStartsAt,\n row.accessExpiresAt,\n row.acquisition.orderId,\n row.acquisition.offerId,\n row.acquisition.paymentStatus,\n row.acquisition.amountMinor,\n row.acquisition.currency,\n row.acquisition.providerId,\n ]),\n );\n}\n"],"mappings":";AAiBA,SAAS,QAAQ,QAA2B;AAC1C,QAAO,OACJ,KAAK,UAAU;EACd,MAAM,OAAO,OAAO,SAAS,GAAG;AAEhC,SAAO,KADM,WAAW,KAAK,KAAK,WAAW,CAAC,IAAI,YAAY,KAAK,KAAK,GAAG,MAAM,OAAO,MACxE,WAAW,MAAK,OAAK,CAAC;GACtC,CACD,KAAK,IAAI;;AAGd,MAAa,sBAAsB,QAAQ;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAgB,mBAAmB,MAAoC;AACrE,QAAO,KAAK,KAAK,QACf,QAAQ;EACN,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI,iBAAiB,WAAW;EAChC,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI,YAAY;EAChB,IAAI,YAAY;EAChB,IAAI,YAAY;EAChB,IAAI,YAAY;EAChB,IAAI,YAAY;EAChB,IAAI,YAAY;EACjB,CAAC,CACH"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
var LmsError = class extends Error {
|
|
3
|
+
constructor(code, message, status = 400) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.name = "PluginRouteError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
function invariant(condition, code, message, status = 400) {
|
|
11
|
+
if (!condition) throw new LmsError(code, message, status);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { invariant as n, LmsError as t };
|
|
16
|
+
//# sourceMappingURL=errors-ChzJS9al.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-ChzJS9al.js","names":[],"sources":["../src/errors.ts"],"sourcesContent":["export class LmsError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly status = 400,\n ) {\n super(message);\n this.name = \"PluginRouteError\";\n }\n}\n\nexport function invariant(\n condition: unknown,\n code: string,\n message: string,\n status = 400,\n): asserts condition {\n if (!condition) throw new LmsError(code, message, status);\n}\n"],"mappings":";AAAA,IAAa,WAAb,cAA8B,MAAM;CAClC,YACE,AAAS,MACT,SACA,AAAS,SAAS,KAClB;AACA,QAAM,QAAQ;EAJL;EAEA;AAGT,OAAK,OAAO;;;AAIhB,SAAgB,UACd,WACA,MACA,SACA,SAAS,KACU;AACnB,KAAI,CAAC,UAAW,OAAM,IAAI,SAAS,MAAM,SAAS,OAAO"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LmsOptions } from "./types.js";
|
|
2
|
+
import { PluginDescriptor } from "emdash";
|
|
3
|
+
|
|
4
|
+
//#region src/constants.d.ts
|
|
5
|
+
declare const PLUGIN_ID = "anantagnanam-lms";
|
|
6
|
+
declare const PLUGIN_VERSION = "0.2.0";
|
|
7
|
+
declare const API_BASE = "/_emdash/api/plugins/anantagnanam-lms";
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/index.d.ts
|
|
10
|
+
declare function anantagnanamLmsPlugin(options?: LmsOptions): PluginDescriptor<LmsOptions>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { API_BASE, type LmsOptions, PLUGIN_ID, PLUGIN_VERSION, anantagnanamLmsPlugin, anantagnanamLmsPlugin as default };
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { a as adminPages, i as PLUGIN_VERSION, r as PLUGIN_ID, t as API_BASE } from "./constants-Cnx7k82Z.js";
|
|
2
|
+
import { t as normalizeLmsOptions } from "./config-BX3beTpM.js";
|
|
3
|
+
|
|
4
|
+
//#region src/index.ts
|
|
5
|
+
function anantagnanamLmsPlugin(options = {}) {
|
|
6
|
+
return {
|
|
7
|
+
id: PLUGIN_ID,
|
|
8
|
+
version: PLUGIN_VERSION,
|
|
9
|
+
format: "native",
|
|
10
|
+
entrypoint: "@anantagnanam/lms/runtime",
|
|
11
|
+
adminEntry: "@anantagnanam/lms/admin",
|
|
12
|
+
adminPages,
|
|
13
|
+
options: normalizeLmsOptions(options)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { API_BASE, PLUGIN_ID, PLUGIN_VERSION, anantagnanamLmsPlugin, anantagnanamLmsPlugin as default };
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { PluginDescriptor } from \"emdash\";\nimport { PLUGIN_ID, PLUGIN_VERSION, adminPages } from \"./constants.js\";\nimport type { LmsOptions } from \"./types.js\";\nimport { normalizeLmsOptions } from \"./config.js\";\n\nexport function anantagnanamLmsPlugin(options: LmsOptions = {}): PluginDescriptor<LmsOptions> {\n return {\n id: PLUGIN_ID,\n version: PLUGIN_VERSION,\n format: \"native\",\n entrypoint: \"@anantagnanam/lms/runtime\",\n adminEntry: \"@anantagnanam/lms/admin\",\n adminPages,\n options: normalizeLmsOptions(options),\n };\n}\n\nexport { PLUGIN_ID, PLUGIN_VERSION, API_BASE } from \"./constants.js\";\nexport type { LmsOptions } from \"./types.js\";\nexport default anantagnanamLmsPlugin;\n"],"mappings":";;;;AAKA,SAAgB,sBAAsB,UAAsB,EAAE,EAAgC;AAC5F,QAAO;EACL,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,YAAY;EACZ,YAAY;EACZ;EACA,SAAS,oBAAoB,QAAQ;EACtC"}
|