@falkenslab/moodle-driver 0.0.0-stage → 0.4.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 (300) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +131 -2
  3. package/dist/areas/activities/build.d.ts +98 -0
  4. package/dist/areas/activities/build.js +248 -0
  5. package/dist/areas/activities/build.js.map +1 -0
  6. package/dist/areas/activities/content.d.ts +53 -0
  7. package/dist/areas/activities/content.js +113 -0
  8. package/dist/areas/activities/content.js.map +1 -0
  9. package/dist/areas/assignments/grader.d.ts +68 -0
  10. package/dist/areas/assignments/grader.js +169 -0
  11. package/dist/areas/assignments/grader.js.map +1 -0
  12. package/dist/areas/assignments/grading.d.ts +86 -0
  13. package/dist/areas/assignments/grading.js +162 -0
  14. package/dist/areas/assignments/grading.js.map +1 -0
  15. package/dist/areas/assignments/student.d.ts +57 -0
  16. package/dist/areas/assignments/student.js +115 -0
  17. package/dist/areas/assignments/student.js.map +1 -0
  18. package/dist/areas/calendar/calendar.d.ts +43 -0
  19. package/dist/areas/calendar/calendar.js +84 -0
  20. package/dist/areas/calendar/calendar.js.map +1 -0
  21. package/dist/areas/completion/completion.d.ts +50 -0
  22. package/dist/areas/completion/completion.js +112 -0
  23. package/dist/areas/completion/completion.js.map +1 -0
  24. package/dist/areas/courses/list.d.ts +59 -0
  25. package/dist/areas/courses/list.js +74 -0
  26. package/dist/areas/courses/list.js.map +1 -0
  27. package/dist/areas/courses/overview.d.ts +83 -0
  28. package/dist/areas/courses/overview.js +137 -0
  29. package/dist/areas/courses/overview.js.map +1 -0
  30. package/dist/areas/courses/state.d.ts +51 -0
  31. package/dist/areas/courses/state.js +45 -0
  32. package/dist/areas/courses/state.js.map +1 -0
  33. package/dist/areas/courses/structure.d.ts +89 -0
  34. package/dist/areas/courses/structure.js +104 -0
  35. package/dist/areas/courses/structure.js.map +1 -0
  36. package/dist/areas/forums/discussions.d.ts +57 -0
  37. package/dist/areas/forums/discussions.js +119 -0
  38. package/dist/areas/forums/discussions.js.map +1 -0
  39. package/dist/areas/forums/posts.d.ts +83 -0
  40. package/dist/areas/forums/posts.js +114 -0
  41. package/dist/areas/forums/posts.js.map +1 -0
  42. package/dist/areas/grades/gradebook.d.ts +104 -0
  43. package/dist/areas/grades/gradebook.js +250 -0
  44. package/dist/areas/grades/gradebook.js.map +1 -0
  45. package/dist/areas/grades/user-report.d.ts +26 -0
  46. package/dist/areas/grades/user-report.js +71 -0
  47. package/dist/areas/grades/user-report.js.map +1 -0
  48. package/dist/areas/h5p/h5p.d.ts +33 -0
  49. package/dist/areas/h5p/h5p.js +104 -0
  50. package/dist/areas/h5p/h5p.js.map +1 -0
  51. package/dist/areas/lessons/lessons.d.ts +60 -0
  52. package/dist/areas/lessons/lessons.js +145 -0
  53. package/dist/areas/lessons/lessons.js.map +1 -0
  54. package/dist/areas/messages/messages.d.ts +68 -0
  55. package/dist/areas/messages/messages.js +84 -0
  56. package/dist/areas/messages/messages.js.map +1 -0
  57. package/dist/areas/participants/participants.d.ts +57 -0
  58. package/dist/areas/participants/participants.js +135 -0
  59. package/dist/areas/participants/participants.js.map +1 -0
  60. package/dist/areas/questions/banks.d.ts +83 -0
  61. package/dist/areas/questions/banks.js +239 -0
  62. package/dist/areas/questions/banks.js.map +1 -0
  63. package/dist/areas/quizzes/attempts.d.ts +123 -0
  64. package/dist/areas/quizzes/attempts.js +300 -0
  65. package/dist/areas/quizzes/attempts.js.map +1 -0
  66. package/dist/areas/quizzes/results.d.ts +36 -0
  67. package/dist/areas/quizzes/results.js +93 -0
  68. package/dist/areas/quizzes/results.js.map +1 -0
  69. package/dist/areas/quizzes/structure.d.ts +42 -0
  70. package/dist/areas/quizzes/structure.js +100 -0
  71. package/dist/areas/quizzes/structure.js.map +1 -0
  72. package/dist/areas/scorm/scorm.d.ts +60 -0
  73. package/dist/areas/scorm/scorm.js +171 -0
  74. package/dist/areas/scorm/scorm.js.map +1 -0
  75. package/dist/areas/site/info.d.ts +25 -0
  76. package/dist/areas/site/info.js +45 -0
  77. package/dist/areas/site/info.js.map +1 -0
  78. package/dist/areas/site/users.d.ts +56 -0
  79. package/dist/areas/site/users.js +89 -0
  80. package/dist/areas/site/users.js.map +1 -0
  81. package/dist/areas/surveys/choice.d.ts +38 -0
  82. package/dist/areas/surveys/choice.js +105 -0
  83. package/dist/areas/surveys/choice.js.map +1 -0
  84. package/dist/areas/surveys/surveys.d.ts +51 -0
  85. package/dist/areas/surveys/surveys.js +201 -0
  86. package/dist/areas/surveys/surveys.js.map +1 -0
  87. package/dist/browser/chromium.d.ts +15 -0
  88. package/dist/browser/chromium.js +53 -0
  89. package/dist/browser/chromium.js.map +1 -0
  90. package/dist/browser/cookies.d.ts +11 -0
  91. package/dist/browser/cookies.js +31 -0
  92. package/dist/browser/cookies.js.map +1 -0
  93. package/dist/browser/manager.d.ts +57 -0
  94. package/dist/browser/manager.js +177 -0
  95. package/dist/browser/manager.js.map +1 -0
  96. package/dist/browser.d.ts +53 -0
  97. package/dist/browser.js +167 -0
  98. package/dist/browser.js.map +1 -0
  99. package/dist/categories.d.ts +28 -0
  100. package/dist/categories.js +225 -0
  101. package/dist/categories.js.map +1 -0
  102. package/dist/chromiumInstaller.d.ts +15 -0
  103. package/dist/chromiumInstaller.js +52 -0
  104. package/dist/chromiumInstaller.js.map +1 -0
  105. package/dist/cli/args.d.ts +33 -0
  106. package/dist/cli/args.js +194 -0
  107. package/dist/cli/args.js.map +1 -0
  108. package/dist/cli/commands.generated.d.ts +4 -0
  109. package/dist/cli/commands.generated.js +2217 -0
  110. package/dist/cli/commands.generated.js.map +1 -0
  111. package/dist/cli/config.d.ts +46 -0
  112. package/dist/cli/config.js +107 -0
  113. package/dist/cli/config.js.map +1 -0
  114. package/dist/cli/main.d.ts +2 -0
  115. package/dist/cli/main.js +19 -0
  116. package/dist/cli/main.js.map +1 -0
  117. package/dist/cli/output.d.ts +4 -0
  118. package/dist/cli/output.js +71 -0
  119. package/dist/cli/output.js.map +1 -0
  120. package/dist/cli/run.d.ts +15 -0
  121. package/dist/cli/run.js +194 -0
  122. package/dist/cli/run.js.map +1 -0
  123. package/dist/cli/spec.d.ts +42 -0
  124. package/dist/cli/spec.js +4 -0
  125. package/dist/cli/spec.js.map +1 -0
  126. package/dist/client.d.ts +224 -0
  127. package/dist/client.js +182 -0
  128. package/dist/client.js.map +1 -0
  129. package/dist/core/ajax.d.ts +25 -0
  130. package/dist/core/ajax.js +85 -0
  131. package/dist/core/ajax.js.map +1 -0
  132. package/dist/core/editor.d.ts +18 -0
  133. package/dist/core/editor.js +51 -0
  134. package/dist/core/editor.js.map +1 -0
  135. package/dist/core/errors.d.ts +12 -0
  136. package/dist/core/errors.js +10 -0
  137. package/dist/core/errors.js.map +1 -0
  138. package/dist/core/files.d.ts +16 -0
  139. package/dist/core/files.js +58 -0
  140. package/dist/core/files.js.map +1 -0
  141. package/dist/core/forms.d.ts +45 -0
  142. package/dist/core/forms.js +200 -0
  143. package/dist/core/forms.js.map +1 -0
  144. package/dist/core/http.d.ts +18 -0
  145. package/dist/core/http.js +22 -0
  146. package/dist/core/http.js.map +1 -0
  147. package/dist/core/inPage.d.ts +8 -0
  148. package/dist/core/inPage.js +10 -0
  149. package/dist/core/inPage.js.map +1 -0
  150. package/dist/core/login.d.ts +40 -0
  151. package/dist/core/login.js +83 -0
  152. package/dist/core/login.js.map +1 -0
  153. package/dist/core/pace.d.ts +4 -0
  154. package/dist/core/pace.js +21 -0
  155. package/dist/core/pace.js.map +1 -0
  156. package/dist/core/session.d.ts +55 -0
  157. package/dist/core/session.js +157 -0
  158. package/dist/core/session.js.map +1 -0
  159. package/dist/core/site.d.ts +8 -0
  160. package/dist/core/site.js +36 -0
  161. package/dist/core/site.js.map +1 -0
  162. package/dist/core/text.d.ts +21 -0
  163. package/dist/core/text.js +113 -0
  164. package/dist/core/text.js.map +1 -0
  165. package/dist/home.d.ts +19 -0
  166. package/dist/home.js +54 -0
  167. package/dist/home.js.map +1 -0
  168. package/dist/index.d.ts +41 -0
  169. package/dist/index.js +52 -0
  170. package/dist/index.js.map +1 -0
  171. package/dist/internals.d.ts +11 -0
  172. package/dist/internals.js +15 -0
  173. package/dist/internals.js.map +1 -0
  174. package/dist/moodle/activities.d.ts +94 -0
  175. package/dist/moodle/activities.js +240 -0
  176. package/dist/moodle/activities.js.map +1 -0
  177. package/dist/moodle/ajax.d.ts +22 -0
  178. package/dist/moodle/ajax.js +91 -0
  179. package/dist/moodle/ajax.js.map +1 -0
  180. package/dist/moodle/assign.d.ts +65 -0
  181. package/dist/moodle/assign.js +162 -0
  182. package/dist/moodle/assign.js.map +1 -0
  183. package/dist/moodle/calendar.d.ts +41 -0
  184. package/dist/moodle/calendar.js +80 -0
  185. package/dist/moodle/calendar.js.map +1 -0
  186. package/dist/moodle/choice.d.ts +33 -0
  187. package/dist/moodle/choice.js +100 -0
  188. package/dist/moodle/choice.js.map +1 -0
  189. package/dist/moodle/completion.d.ts +48 -0
  190. package/dist/moodle/completion.js +108 -0
  191. package/dist/moodle/completion.js.map +1 -0
  192. package/dist/moodle/content.d.ts +43 -0
  193. package/dist/moodle/content.js +105 -0
  194. package/dist/moodle/content.js.map +1 -0
  195. package/dist/moodle/course.d.ts +51 -0
  196. package/dist/moodle/course.js +45 -0
  197. package/dist/moodle/course.js.map +1 -0
  198. package/dist/moodle/courses.d.ts +57 -0
  199. package/dist/moodle/courses.js +70 -0
  200. package/dist/moodle/courses.js.map +1 -0
  201. package/dist/moodle/editor.d.ts +18 -0
  202. package/dist/moodle/editor.js +50 -0
  203. package/dist/moodle/editor.js.map +1 -0
  204. package/dist/moodle/files.d.ts +16 -0
  205. package/dist/moodle/files.js +57 -0
  206. package/dist/moodle/files.js.map +1 -0
  207. package/dist/moodle/forms.d.ts +44 -0
  208. package/dist/moodle/forms.js +199 -0
  209. package/dist/moodle/forms.js.map +1 -0
  210. package/dist/moodle/forum.d.ts +55 -0
  211. package/dist/moodle/forum.js +115 -0
  212. package/dist/moodle/forum.js.map +1 -0
  213. package/dist/moodle/forumPosts.d.ts +83 -0
  214. package/dist/moodle/forumPosts.js +113 -0
  215. package/dist/moodle/forumPosts.js.map +1 -0
  216. package/dist/moodle/gradebook.d.ts +102 -0
  217. package/dist/moodle/gradebook.js +246 -0
  218. package/dist/moodle/gradebook.js.map +1 -0
  219. package/dist/moodle/grades.d.ts +24 -0
  220. package/dist/moodle/grades.js +67 -0
  221. package/dist/moodle/grades.js.map +1 -0
  222. package/dist/moodle/grading.d.ts +92 -0
  223. package/dist/moodle/grading.js +161 -0
  224. package/dist/moodle/grading.js.map +1 -0
  225. package/dist/moodle/h5p.d.ts +31 -0
  226. package/dist/moodle/h5p.js +100 -0
  227. package/dist/moodle/h5p.js.map +1 -0
  228. package/dist/moodle/inPage.d.ts +8 -0
  229. package/dist/moodle/inPage.js +10 -0
  230. package/dist/moodle/inPage.js.map +1 -0
  231. package/dist/moodle/lesson.d.ts +57 -0
  232. package/dist/moodle/lesson.js +140 -0
  233. package/dist/moodle/lesson.js.map +1 -0
  234. package/dist/moodle/login.d.ts +37 -0
  235. package/dist/moodle/login.js +77 -0
  236. package/dist/moodle/login.js.map +1 -0
  237. package/dist/moodle/messages.d.ts +66 -0
  238. package/dist/moodle/messages.js +80 -0
  239. package/dist/moodle/messages.js.map +1 -0
  240. package/dist/moodle/overview.d.ts +83 -0
  241. package/dist/moodle/overview.js +137 -0
  242. package/dist/moodle/overview.js.map +1 -0
  243. package/dist/moodle/pace.d.ts +4 -0
  244. package/dist/moodle/pace.js +19 -0
  245. package/dist/moodle/pace.js.map +1 -0
  246. package/dist/moodle/participants.d.ts +55 -0
  247. package/dist/moodle/participants.js +131 -0
  248. package/dist/moodle/participants.js.map +1 -0
  249. package/dist/moodle/questionBank.d.ts +81 -0
  250. package/dist/moodle/questionBank.js +235 -0
  251. package/dist/moodle/questionBank.js.map +1 -0
  252. package/dist/moodle/quiz.d.ts +117 -0
  253. package/dist/moodle/quiz.js +291 -0
  254. package/dist/moodle/quiz.js.map +1 -0
  255. package/dist/moodle/quizResults.d.ts +36 -0
  256. package/dist/moodle/quizResults.js +93 -0
  257. package/dist/moodle/quizResults.js.map +1 -0
  258. package/dist/moodle/quizStructure.d.ts +42 -0
  259. package/dist/moodle/quizStructure.js +100 -0
  260. package/dist/moodle/quizStructure.js.map +1 -0
  261. package/dist/moodle/session.d.ts +39 -0
  262. package/dist/moodle/session.js +99 -0
  263. package/dist/moodle/session.js.map +1 -0
  264. package/dist/moodle/site.d.ts +8 -0
  265. package/dist/moodle/site.js +36 -0
  266. package/dist/moodle/site.js.map +1 -0
  267. package/dist/moodle/siteInfo.d.ts +25 -0
  268. package/dist/moodle/siteInfo.js +45 -0
  269. package/dist/moodle/siteInfo.js.map +1 -0
  270. package/dist/moodle/structure.d.ts +94 -0
  271. package/dist/moodle/structure.js +103 -0
  272. package/dist/moodle/structure.js.map +1 -0
  273. package/dist/moodle/submission.d.ts +48 -0
  274. package/dist/moodle/submission.js +109 -0
  275. package/dist/moodle/submission.js.map +1 -0
  276. package/dist/moodle/survey.d.ts +47 -0
  277. package/dist/moodle/survey.js +197 -0
  278. package/dist/moodle/survey.js.map +1 -0
  279. package/dist/moodle/text.d.ts +21 -0
  280. package/dist/moodle/text.js +113 -0
  281. package/dist/moodle/text.js.map +1 -0
  282. package/dist/moodle/user.d.ts +54 -0
  283. package/dist/moodle/user.js +78 -0
  284. package/dist/moodle/user.js.map +1 -0
  285. package/dist/options.d.ts +30 -0
  286. package/dist/options.js +35 -0
  287. package/dist/options.js.map +1 -0
  288. package/dist/sessionCookies.d.ts +11 -0
  289. package/dist/sessionCookies.js +31 -0
  290. package/dist/sessionCookies.js.map +1 -0
  291. package/dist/testing/fakeMoodle.d.ts +55 -0
  292. package/dist/testing/fakeMoodle.js +103 -0
  293. package/dist/testing/fakeMoodle.js.map +1 -0
  294. package/dist/testing/gradingPanel.d.ts +6 -0
  295. package/dist/testing/gradingPanel.js +22 -0
  296. package/dist/testing/gradingPanel.js.map +1 -0
  297. package/dist/testing/index.d.ts +5 -0
  298. package/dist/testing/index.js +18 -0
  299. package/dist/testing/index.js.map +1 -0
  300. package/package.json +78 -4
@@ -0,0 +1,4 @@
1
+ // The shape of the command table the `moodle` command is built from (ADR-012): one command per method
2
+ // of the Moodle object, generated from its types by scripts/generate-cli-commands.mjs.
3
+ export {};
4
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/cli/spec.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,uFAAuF"}
@@ -0,0 +1,224 @@
1
+ import type { BrowserContext, Page } from "playwright-core";
2
+ import { type BrowserManager } from "./browser/manager.js";
3
+ import { type BrowserOptions, type Trail } from "./options.js";
4
+ import { activitySettings, addSection, createActivity, deleteActivity, deleteSection, duplicateActivity, editActivity, editSection, updateActivity } from "./areas/activities/build.js";
5
+ import { createEvent, deleteEvent, upcomingEvents } from "./areas/calendar/calendar.js";
6
+ import { answerChoice, getChoice } from "./areas/surveys/choice.js";
7
+ import { completionReport, overrideCompletion, setCompletion } from "./areas/completion/completion.js";
8
+ import { type ActivityContent, type ContentType } from "./areas/activities/content.js";
9
+ import { listCourses, updateCourse } from "./areas/courses/list.js";
10
+ import { type DownloadedFile } from "./core/files.js";
11
+ import { openForm } from "./core/forms.js";
12
+ import { discussion, forumDiscussions, replyToPost, setDiscussionState, startDiscussion } from "./areas/forums/posts.js";
13
+ import { addGradeCategory, gradebookSetup, graderReport, updateGradeItem } from "./areas/grades/gradebook.js";
14
+ import { myGrades } from "./areas/grades/user-report.js";
15
+ import { assignmentSubmissions, gradeSubmission, grantExtension, rubric } from "./areas/assignments/grading.js";
16
+ import { h5pActivity } from "./areas/h5p/h5p.js";
17
+ import { scorm, type OpenedScorm } from "./areas/scorm/scorm.js";
18
+ import { answerLessonPage, lessonPage, type LessonPage } from "./areas/lessons/lessons.js";
19
+ import { type LoginResult } from "./core/login.js";
20
+ import { conversation, conversations, markNotificationsRead, notifications, sendMessage } from "./areas/messages/messages.js";
21
+ import { activitiesOverview, courseUpdates, deadlines } from "./areas/courses/overview.js";
22
+ import { groups, participantFilters, participants } from "./areas/participants/participants.js";
23
+ import { createQuestion, importQuestions, questionBanks, questions } from "./areas/questions/banks.js";
24
+ import { answerQuizQuestions, finishQuizAttempt, quizInfo, readAttempt, readReview, setQuizOverride, startQuizAttempt, type Question } from "./areas/quizzes/attempts.js";
25
+ import { quizResults } from "./areas/quizzes/results.js";
26
+ import { addQuestionsToQuiz, quizStructure } from "./areas/quizzes/structure.js";
27
+ import { logOut, openSitePage } from "./core/session.js";
28
+ import { courseActivityTypes, publicSiteInfo } from "./areas/site/info.js";
29
+ import { courseStructure, listAssignments, pendingActivities } from "./areas/courses/structure.js";
30
+ import { saveSubmission, studentAssignment, submitForGrading } from "./areas/assignments/student.js";
31
+ import { getSurvey, submitSurvey } from "./areas/surveys/surveys.js";
32
+ import { courseAbilities, courseRoles, siteName, userById, whoAmI } from "./areas/site/users.js";
33
+ /**
34
+ * The functions that take the browser context and the site first, of the high-level API: each becomes
35
+ * a method of the same name without those two parameters. The pieces they're built from (an
36
+ * assignment's ids, its grading panel, a quiz attempt's steps…) stay functions only; the ones that
37
+ * use the object's defaults (`trail`, `downloadDir`…) and `callService`, generic, are bound by hand.
38
+ */
39
+ declare const SITE_FUNCTIONS: {
40
+ activitiesOverview: typeof activitiesOverview;
41
+ activitySettings: typeof activitySettings;
42
+ addGradeCategory: typeof addGradeCategory;
43
+ addQuestionsToQuiz: typeof addQuestionsToQuiz;
44
+ addSection: typeof addSection;
45
+ answerChoice: typeof answerChoice;
46
+ assignmentSubmissions: typeof assignmentSubmissions;
47
+ completionReport: typeof completionReport;
48
+ conversation: typeof conversation;
49
+ conversations: typeof conversations;
50
+ courseAbilities: typeof courseAbilities;
51
+ courseActivityTypes: typeof courseActivityTypes;
52
+ courseRoles: typeof courseRoles;
53
+ courseStructure: typeof courseStructure;
54
+ courseUpdates: typeof courseUpdates;
55
+ createActivity: typeof createActivity;
56
+ createEvent: typeof createEvent;
57
+ createQuestion: typeof createQuestion;
58
+ deadlines: typeof deadlines;
59
+ deleteActivity: typeof deleteActivity;
60
+ deleteEvent: typeof deleteEvent;
61
+ deleteSection: typeof deleteSection;
62
+ discussion: typeof discussion;
63
+ duplicateActivity: typeof duplicateActivity;
64
+ editActivity: typeof editActivity;
65
+ editSection: typeof editSection;
66
+ finishQuizAttempt: typeof finishQuizAttempt;
67
+ forumDiscussions: typeof forumDiscussions;
68
+ getChoice: typeof getChoice;
69
+ getSurvey: typeof getSurvey;
70
+ gradeSubmission: typeof gradeSubmission;
71
+ gradebookSetup: typeof gradebookSetup;
72
+ graderReport: typeof graderReport;
73
+ grantExtension: typeof grantExtension;
74
+ groups: typeof groups;
75
+ h5pActivity: typeof h5pActivity;
76
+ scorm: typeof scorm;
77
+ importQuestions: typeof importQuestions;
78
+ lessonPage: typeof lessonPage;
79
+ listAssignments: typeof listAssignments;
80
+ listCourses: typeof listCourses;
81
+ logOut: typeof logOut;
82
+ markNotificationsRead: typeof markNotificationsRead;
83
+ myGrades: typeof myGrades;
84
+ notifications: typeof notifications;
85
+ openForm: typeof openForm;
86
+ openSitePage: typeof openSitePage;
87
+ overrideCompletion: typeof overrideCompletion;
88
+ participantFilters: typeof participantFilters;
89
+ participants: typeof participants;
90
+ pendingActivities: typeof pendingActivities;
91
+ questionBanks: typeof questionBanks;
92
+ questions: typeof questions;
93
+ quizInfo: typeof quizInfo;
94
+ quizResults: typeof quizResults;
95
+ quizStructure: typeof quizStructure;
96
+ readAttempt: typeof readAttempt;
97
+ readReview: typeof readReview;
98
+ replyToPost: typeof replyToPost;
99
+ rubric: typeof rubric;
100
+ saveSubmission: typeof saveSubmission;
101
+ sendMessage: typeof sendMessage;
102
+ setCompletion: typeof setCompletion;
103
+ setDiscussionState: typeof setDiscussionState;
104
+ setQuizOverride: typeof setQuizOverride;
105
+ siteName: typeof siteName;
106
+ startDiscussion: typeof startDiscussion;
107
+ startQuizAttempt: typeof startQuizAttempt;
108
+ studentAssignment: typeof studentAssignment;
109
+ submitForGrading: typeof submitForGrading;
110
+ submitSurvey: typeof submitSurvey;
111
+ upcomingEvents: typeof upcomingEvents;
112
+ updateActivity: typeof updateActivity;
113
+ updateCourse: typeof updateCourse;
114
+ updateGradeItem: typeof updateGradeItem;
115
+ userById: typeof userById;
116
+ whoAmI: typeof whoAmI;
117
+ };
118
+ type SiteFunctions = typeof SITE_FUNCTIONS;
119
+ /** A function of `(context, siteUrl, ...rest)` as a method of `(...rest)`. */
120
+ type Bound<F> = F extends (context: BrowserContext, siteUrl: string, ...rest: infer A) => infer R ? (...rest: A) => R : never;
121
+ /** The methods bound from the site functions, each named and documented as its function. */
122
+ export type MoodleMethods = {
123
+ [K in keyof SiteFunctions]: Bound<SiteFunctions[K]>;
124
+ };
125
+ /** The names of the methods a `Moodle` has from the driver's functions, one per function of that name. */
126
+ export declare const MOODLE_METHODS: readonly string[];
127
+ /** What the object does when a call doesn't say: every one can still be given per call. */
128
+ export interface MoodleDefaults {
129
+ /** How student actions read and answer: "realistic" (the default, at a reader's pace) or "fast" (ADR-005). */
130
+ trail?: Trail;
131
+ /** Called every few seconds while a student action waits at a reader's pace: the seconds elapsed, and the total when known. */
132
+ onProgress?: (elapsedSeconds: number, totalSeconds?: number) => void;
133
+ /** How long `logIn` waits for the person to log in, in milliseconds: five minutes unless given. */
134
+ loginTimeoutMs?: number;
135
+ /** Where `downloadFile` saves files when not given a folder (an absolute path). */
136
+ downloadDir?: string;
137
+ }
138
+ /** A student action's pace for one call, over the object's defaults. */
139
+ type PaceOptions<P> = {
140
+ trail?: Trail;
141
+ onProgress?: P;
142
+ };
143
+ /**
144
+ * One Moodle site worked through one browser: the driver's operations as methods, without the
145
+ * browser context and the site the functions take first (`moodle.listCourses()` is
146
+ * `listCourses(context, site)`), plus the session and the browser. The pieces the operations are
147
+ * built from stay functions only.
148
+ */
149
+ export interface Moodle extends MoodleMethods {
150
+ /** The site's base URL, normalized (a trailing slash). */
151
+ readonly site: string;
152
+ /** The browser manager underneath, for what the methods don't cover. */
153
+ readonly browser: BrowserManager;
154
+ /** The defaults the object was made with. */
155
+ readonly defaults: Readonly<MoodleDefaults>;
156
+ /** The browser's context, launching it if needed: what the functions take. */
157
+ context(): Promise<BrowserContext>;
158
+ /** Makes sure there's a session: at once if there is one, else a window where the person logs in (`loginTimeoutMs` by default). */
159
+ logIn(options?: {
160
+ timeoutMs?: number;
161
+ onWait?: (elapsedMs: number) => void;
162
+ }): Promise<LoginResult>;
163
+ /** What the site tells anyone before logging in, without the browser. */
164
+ publicSiteInfo(): ReturnType<typeof publicSiteInfo>;
165
+ /** Calls one of Moodle's AJAX services as the logged-in person. */
166
+ callService<T>(methodname: string, args: Record<string, unknown>): Promise<T>;
167
+ /** `activityContent`, at the object's `trail` unless given. */
168
+ activityContent(activity: {
169
+ id: number;
170
+ type: string;
171
+ }, options?: PaceOptions<(secondsRead: number) => void>): Promise<ActivityContent>;
172
+ activityContent(activityId: number, type: ContentType, options?: PaceOptions<(secondsRead: number) => void>): Promise<ActivityContent>;
173
+ /** `answerQuizQuestions`, at the object's `trail` unless given. */
174
+ answerQuizQuestions(attemptId: number, answers: Parameters<typeof answerQuizQuestions>[3], options?: PaceOptions<(elapsed: number, total: number) => void>): Promise<{
175
+ changed: string;
176
+ attemptId: number;
177
+ questions: Question[];
178
+ }>;
179
+ /** `answerLessonPage`, at the object's `trail` unless given. */
180
+ answerLessonPage(activityId: number, answer: Parameters<typeof answerLessonPage>[3], options?: PaceOptions<(elapsed: number, total: number) => void>): Promise<{
181
+ changed: string;
182
+ feedback?: LessonPage;
183
+ page: LessonPage;
184
+ }>;
185
+ /** `downloadFile`, into the object's `downloadDir` unless given a folder. */
186
+ downloadFile(url: string, destDir?: string): Promise<DownloadedFile>;
187
+ /** The working tab a program drives itself (ADR-007). */
188
+ tab(): Promise<Page>;
189
+ /** `openScorm`: a SCORM's player, on the working tab. */
190
+ openScorm(activityId: number, options?: {
191
+ scoId?: number;
192
+ newAttempt?: boolean;
193
+ }): Promise<OpenedScorm>;
194
+ /** Whether the browser shows a window now. */
195
+ visible(): boolean;
196
+ /** Shows the browser and follows the pages methods open, or hides it. */
197
+ setVisible(visible: boolean): Promise<void>;
198
+ /** Saves the session cookies of the open browser now. */
199
+ saveSession(): Promise<void>;
200
+ /** Saves the session and closes the browser; the next call opens it again. */
201
+ close(): Promise<void>;
202
+ /** `close()`, so `await using moodle = createMoodle(…)` closes the browser when the block ends. */
203
+ [Symbol.asyncDispose](): Promise<void>;
204
+ }
205
+ /** A site, the browser to work it with (its options for a new browser manager, or one already made), and the object's defaults. */
206
+ export type MoodleOptions = MoodleDefaults & (({
207
+ site: string;
208
+ } & BrowserOptions) | {
209
+ site: string;
210
+ browser: BrowserManager;
211
+ });
212
+ /**
213
+ * Works one Moodle site through a browser: give the site and the browser's options (or a browser
214
+ * manager), and optionally the defaults its calls use; then call the driver's operations as methods.
215
+ *
216
+ * ```ts
217
+ * const moodle = createMoodle({ site: "https://campus.example.org/", profileDir: "/home/me/.moodle-profile", headless: true, downloadBrowser: true, trail: "fast" });
218
+ * await moodle.logIn();
219
+ * const courses = await moodle.listCourses();
220
+ * await moodle.close();
221
+ * ```
222
+ */
223
+ export declare function createMoodle(options: MoodleOptions): Moodle;
224
+ export {};
package/dist/client.js ADDED
@@ -0,0 +1,182 @@
1
+ import { createBrowserManager } from "./browser/manager.js";
2
+ import { parseSiteUrl } from "./options.js";
3
+ import { activitySettings, addSection, createActivity, deleteActivity, deleteSection, duplicateActivity, editActivity, editSection, updateActivity } from "./areas/activities/build.js";
4
+ import { callService } from "./core/ajax.js";
5
+ import { createEvent, deleteEvent, upcomingEvents } from "./areas/calendar/calendar.js";
6
+ import { answerChoice, getChoice } from "./areas/surveys/choice.js";
7
+ import { completionReport, overrideCompletion, setCompletion } from "./areas/completion/completion.js";
8
+ import { activityContent } from "./areas/activities/content.js";
9
+ import { listCourses, updateCourse } from "./areas/courses/list.js";
10
+ import { downloadFile } from "./core/files.js";
11
+ import { openForm } from "./core/forms.js";
12
+ import { discussion, forumDiscussions, replyToPost, setDiscussionState, startDiscussion } from "./areas/forums/posts.js";
13
+ import { addGradeCategory, gradebookSetup, graderReport, updateGradeItem } from "./areas/grades/gradebook.js";
14
+ import { myGrades } from "./areas/grades/user-report.js";
15
+ import { assignmentSubmissions, gradeSubmission, grantExtension, rubric } from "./areas/assignments/grading.js";
16
+ import { h5pActivity } from "./areas/h5p/h5p.js";
17
+ import { openScorm, scorm } from "./areas/scorm/scorm.js";
18
+ import { answerLessonPage, lessonPage } from "./areas/lessons/lessons.js";
19
+ import { logIn } from "./core/login.js";
20
+ import { conversation, conversations, markNotificationsRead, notifications, sendMessage } from "./areas/messages/messages.js";
21
+ import { activitiesOverview, courseUpdates, deadlines } from "./areas/courses/overview.js";
22
+ import { groups, participantFilters, participants } from "./areas/participants/participants.js";
23
+ import { createQuestion, importQuestions, questionBanks, questions } from "./areas/questions/banks.js";
24
+ import { answerQuizQuestions, finishQuizAttempt, quizInfo, readAttempt, readReview, setQuizOverride, startQuizAttempt } from "./areas/quizzes/attempts.js";
25
+ import { quizResults } from "./areas/quizzes/results.js";
26
+ import { addQuestionsToQuiz, quizStructure } from "./areas/quizzes/structure.js";
27
+ import { logOut, openSitePage } from "./core/session.js";
28
+ import { courseActivityTypes, publicSiteInfo } from "./areas/site/info.js";
29
+ import { courseStructure, listAssignments, pendingActivities } from "./areas/courses/structure.js";
30
+ import { saveSubmission, studentAssignment, submitForGrading } from "./areas/assignments/student.js";
31
+ import { getSurvey, submitSurvey } from "./areas/surveys/surveys.js";
32
+ import { courseAbilities, courseRoles, siteName, userById, whoAmI } from "./areas/site/users.js";
33
+ import { MoodleError } from "./core/errors.js";
34
+ /**
35
+ * The functions that take the browser context and the site first, of the high-level API: each becomes
36
+ * a method of the same name without those two parameters. The pieces they're built from (an
37
+ * assignment's ids, its grading panel, a quiz attempt's steps…) stay functions only; the ones that
38
+ * use the object's defaults (`trail`, `downloadDir`…) and `callService`, generic, are bound by hand.
39
+ */
40
+ const SITE_FUNCTIONS = {
41
+ activitiesOverview,
42
+ activitySettings,
43
+ addGradeCategory,
44
+ addQuestionsToQuiz,
45
+ addSection,
46
+ answerChoice,
47
+ assignmentSubmissions,
48
+ completionReport,
49
+ conversation,
50
+ conversations,
51
+ courseAbilities,
52
+ courseActivityTypes,
53
+ courseRoles,
54
+ courseStructure,
55
+ courseUpdates,
56
+ createActivity,
57
+ createEvent,
58
+ createQuestion,
59
+ deadlines,
60
+ deleteActivity,
61
+ deleteEvent,
62
+ deleteSection,
63
+ discussion,
64
+ duplicateActivity,
65
+ editActivity,
66
+ editSection,
67
+ finishQuizAttempt,
68
+ forumDiscussions,
69
+ getChoice,
70
+ getSurvey,
71
+ gradeSubmission,
72
+ gradebookSetup,
73
+ graderReport,
74
+ grantExtension,
75
+ groups,
76
+ h5pActivity,
77
+ scorm,
78
+ importQuestions,
79
+ lessonPage,
80
+ listAssignments,
81
+ listCourses,
82
+ logOut,
83
+ markNotificationsRead,
84
+ myGrades,
85
+ notifications,
86
+ openForm,
87
+ openSitePage,
88
+ overrideCompletion,
89
+ participantFilters,
90
+ participants,
91
+ pendingActivities,
92
+ questionBanks,
93
+ questions,
94
+ quizInfo,
95
+ quizResults,
96
+ quizStructure,
97
+ readAttempt,
98
+ readReview,
99
+ replyToPost,
100
+ rubric,
101
+ saveSubmission,
102
+ sendMessage,
103
+ setCompletion,
104
+ setDiscussionState,
105
+ setQuizOverride,
106
+ siteName,
107
+ startDiscussion,
108
+ startQuizAttempt,
109
+ studentAssignment,
110
+ submitForGrading,
111
+ submitSurvey,
112
+ upcomingEvents,
113
+ updateActivity,
114
+ updateCourse,
115
+ updateGradeItem,
116
+ userById,
117
+ whoAmI,
118
+ };
119
+ // Functions bound by hand, with the object's defaults: methods of the same name all the same.
120
+ const DEFAULTED = ["activityContent", "answerQuizQuestions", "answerLessonPage", "downloadFile"];
121
+ /** The names of the methods a `Moodle` has from the driver's functions, one per function of that name. */
122
+ export const MOODLE_METHODS = [...Object.keys(SITE_FUNCTIONS), ...DEFAULTED];
123
+ /**
124
+ * Works one Moodle site through a browser: give the site and the browser's options (or a browser
125
+ * manager), and optionally the defaults its calls use; then call the driver's operations as methods.
126
+ *
127
+ * ```ts
128
+ * const moodle = createMoodle({ site: "https://campus.example.org/", profileDir: "/home/me/.moodle-profile", headless: true, downloadBrowser: true, trail: "fast" });
129
+ * await moodle.logIn();
130
+ * const courses = await moodle.listCourses();
131
+ * await moodle.close();
132
+ * ```
133
+ */
134
+ export function createMoodle(options) {
135
+ const site = parseSiteUrl(options.site);
136
+ const browser = "browser" in options ? options.browser : createBrowserManager(options);
137
+ const defaults = { trail: options.trail, onProgress: options.onProgress, loginTimeoutMs: options.loginTimeoutMs, downloadDir: options.downloadDir };
138
+ const bound = {};
139
+ for (const [name, fn] of Object.entries(SITE_FUNCTIONS)) {
140
+ const call = fn;
141
+ bound[name] = async (...args) => call(await browser.context(), site, ...args);
142
+ }
143
+ // Only what's set: an undefined option would hide the function's own default.
144
+ const pace = (given = {}, progress) => ({
145
+ ...(given.trail ?? defaults.trail ? { trail: given.trail ?? defaults.trail } : {}),
146
+ ...(given.onProgress ?? progress ? { onProgress: given.onProgress ?? progress } : {}),
147
+ });
148
+ const onProgress = defaults.onProgress;
149
+ return {
150
+ ...bound,
151
+ site,
152
+ browser,
153
+ defaults,
154
+ context: () => browser.context(),
155
+ logIn: (loginOptions = {}) => logIn(browser, site, { ...loginOptions, timeoutMs: loginOptions.timeoutMs ?? defaults.loginTimeoutMs }),
156
+ publicSiteInfo: () => publicSiteInfo(site),
157
+ callService: async (methodname, args) => callService(await browser.context(), site, methodname, args),
158
+ activityContent: async (activityOrId, typeOrOptions, given) => {
159
+ const context = await browser.context();
160
+ const progress = onProgress && ((read) => onProgress(read));
161
+ if (typeof activityOrId === "number")
162
+ return activityContent(context, site, activityOrId, typeOrOptions, pace(given, progress));
163
+ return activityContent(context, site, activityOrId, pace(typeOrOptions, progress));
164
+ },
165
+ answerQuizQuestions: async (attemptId, answers, given) => answerQuizQuestions(await browser.context(), site, attemptId, answers, pace(given, onProgress)),
166
+ answerLessonPage: async (activityId, answer, given) => answerLessonPage(await browser.context(), site, activityId, answer, pace(given, onProgress)),
167
+ downloadFile: async (url, destDir) => {
168
+ const folder = destDir ?? defaults.downloadDir;
169
+ if (!folder)
170
+ throw new MoodleError("Give downloadFile a folder, or createMoodle a downloadDir.", "invalid-input");
171
+ return downloadFile(await browser.context(), site, url, folder);
172
+ },
173
+ tab: () => browser.tab(),
174
+ openScorm: (activityId, scormOptions) => openScorm(browser, site, activityId, scormOptions),
175
+ visible: () => browser.visible(),
176
+ setVisible: (visible) => browser.setVisible(visible),
177
+ saveSession: () => browser.saveSession(),
178
+ close: () => browser.close(),
179
+ [Symbol.asyncDispose]: () => browser.close(),
180
+ };
181
+ }
182
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { BrowserContext } from "playwright-core";
2
+ import { MoodleError } from "./errors.js";
3
+ /** A Moodle AJAX service answered with an exception. */
4
+ export declare class MoodleServiceError extends MoodleError {
5
+ readonly methodname: string;
6
+ readonly errorcode: string;
7
+ name: string;
8
+ constructor(methodname: string, errorcode: string, message: string);
9
+ }
10
+ /** What `M.cfg` says about the logged-in person. */
11
+ export interface PageConfig {
12
+ userId: number;
13
+ language: string;
14
+ timeZone: string;
15
+ }
16
+ /** The response of `lib/ajax/service.php` for one request: `data`, or throws. */
17
+ export declare function parseServiceResponse<T>(methodname: string, status: number, body: string): T;
18
+ /**
19
+ * Calls one of Moodle's AJAX services as the logged-in person: a request to `lib/ajax/service.php`
20
+ * with the profile's session and its sesskey, as Moodle's pages make them, without a tab (ADR-004,
21
+ * ADR-011). Throws `NotLoggedInError` when there's no session, `MoodleServiceError` when the service fails.
22
+ */
23
+ export declare function callService<T>(context: BrowserContext, siteUrl: string, methodname: string, args: Record<string, unknown>): Promise<T>;
24
+ /** The logged-in person's id, interface language and time zone, from `M.cfg`, read now: someone else may have logged in since. */
25
+ export declare function readPageConfig(context: BrowserContext, siteUrl: string): Promise<PageConfig>;
@@ -0,0 +1,85 @@
1
+ import { NotLoggedInError, fetchSitePage, readMoodleConfig } from "./session.js";
2
+ import { MoodleError } from "./errors.js";
3
+ import { siteFetch } from "./http.js";
4
+ /** A Moodle AJAX service answered with an exception. */
5
+ export class MoodleServiceError extends MoodleError {
6
+ methodname;
7
+ errorcode;
8
+ name = "MoodleServiceError";
9
+ constructor(methodname, errorcode, message) {
10
+ super(`Moodle's ${methodname} failed (${errorcode}): ${message}`, "moodle-service");
11
+ this.methodname = methodname;
12
+ this.errorcode = errorcode;
13
+ }
14
+ }
15
+ // What service.php answers when the session is gone or the sesskey is from an older one.
16
+ const SESSION_ERRORS = new Set(["servicerequireslogin", "invalidsesskey"]);
17
+ // A light page that needs a session: its `M.cfg` carries the session's sesskey and the person's settings.
18
+ const SESSION_PAGE = "user/preferences.php";
19
+ // Per context: the site, the session's sesskey and the person's settings, read once from a page (ADR-011).
20
+ const sessions = new WeakMap();
21
+ async function session(context, siteUrl, fresh) {
22
+ const current = sessions.get(context);
23
+ // The program may have changed the site since the sesskey was read.
24
+ if (current && current.siteUrl === siteUrl && !fresh)
25
+ return current;
26
+ const { html } = await fetchSitePage(context, siteUrl, SESSION_PAGE, { follow: false });
27
+ const cfg = readMoodleConfig(html) ?? {};
28
+ if (typeof cfg.sesskey !== "string")
29
+ throw new NotLoggedInError();
30
+ const config = { userId: Number(cfg.userId), language: String(cfg.language), timeZone: String(cfg.usertimezone) };
31
+ const next = { siteUrl, sesskey: cfg.sesskey, config };
32
+ sessions.set(context, next);
33
+ return next;
34
+ }
35
+ /** The response of `lib/ajax/service.php` for one request: `data`, or throws. */
36
+ export function parseServiceResponse(methodname, status, body) {
37
+ let responses;
38
+ try {
39
+ responses = JSON.parse(body);
40
+ }
41
+ catch {
42
+ throw new MoodleServiceError(methodname, `http${status}`, "the answer isn't JSON");
43
+ }
44
+ const response = (Array.isArray(responses) ? responses[0] : responses);
45
+ if (!response)
46
+ throw new MoodleServiceError(methodname, `http${status}`, "empty answer");
47
+ if (response.error === false)
48
+ return response.data;
49
+ // A failure before any function runs (bad sesskey) comes as a bare exception object.
50
+ const exception = response.exception ?? response;
51
+ throw new MoodleServiceError(methodname, exception.errorcode ?? "unknown", exception.message ?? "no message");
52
+ }
53
+ /**
54
+ * Calls one of Moodle's AJAX services as the logged-in person: a request to `lib/ajax/service.php`
55
+ * with the profile's session and its sesskey, as Moodle's pages make them, without a tab (ADR-004,
56
+ * ADR-011). Throws `NotLoggedInError` when there's no session, `MoodleServiceError` when the service fails.
57
+ */
58
+ export async function callService(context, siteUrl, methodname, args) {
59
+ for (const fresh of [false, true]) {
60
+ const { sesskey } = await session(context, siteUrl, fresh);
61
+ const url = new URL(`lib/ajax/service.php?sesskey=${encodeURIComponent(sesskey)}&info=${encodeURIComponent(methodname)}`, siteUrl).href;
62
+ const { status, body } = await siteFetch(context, url, {
63
+ method: "POST",
64
+ headers: { "Content-Type": "application/json" },
65
+ body: JSON.stringify([{ index: 0, methodname, args }]),
66
+ });
67
+ try {
68
+ return parseServiceResponse(methodname, status, body);
69
+ }
70
+ catch (error) {
71
+ const sessionError = error instanceof MoodleServiceError && SESSION_ERRORS.has(error.errorcode);
72
+ if (!sessionError)
73
+ throw error;
74
+ // The sesskey may be stale (a new login, an expiry): reading it again tells which.
75
+ if (fresh)
76
+ throw new NotLoggedInError();
77
+ }
78
+ }
79
+ throw new NotLoggedInError(); // Unreachable: the fresh attempt returns or throws.
80
+ }
81
+ /** The logged-in person's id, interface language and time zone, from `M.cfg`, read now: someone else may have logged in since. */
82
+ export async function readPageConfig(context, siteUrl) {
83
+ return (await session(context, siteUrl, true)).config;
84
+ }
85
+ //# sourceMappingURL=ajax.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ajax.js","sourceRoot":"","sources":["../../src/core/ajax.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { BrowserContext } from "playwright-core";
2
+ /** The course editor's actions this server uses (`core_courseformat\stateactions`, Moodle 4.0–5.2). */
3
+ export type EditorAction = "cm_show" | "cm_hide" | "cm_stealth" | "cm_move" | "cm_duplicate" | "cm_delete" | "section_add" | "section_show" | "section_hide" | "section_move_after" | "section_delete";
4
+ /**
5
+ * Runs one of the course editor's actions through its own service (ADR-004), as the editor does:
6
+ * ids of activities or sections, and a target section (`cm_move`: at its end; `section_add`,
7
+ * `section_move_after`: after it) or a target activity (`cm_move`: before it).
8
+ */
9
+ export declare function editCourse(context: BrowserContext, siteUrl: string, courseId: number, action: EditorAction, ids: number[], target?: {
10
+ sectionId?: number;
11
+ activityId?: number;
12
+ }): Promise<void>;
13
+ /** The course format (topics, weeks…), a class of the course page's body: no service tells teachers. */
14
+ export declare function courseFormat(context: BrowserContext, siteUrl: string, courseId: number): Promise<string>;
15
+ /** Renames an activity, as the course page's in-place editor does. */
16
+ export declare function renameActivity(context: BrowserContext, siteUrl: string, activityId: number, name: string): Promise<void>;
17
+ /** Renames a section through its course format's in-place editor. */
18
+ export declare function renameSection(context: BrowserContext, siteUrl: string, courseId: number, sectionId: number, name: string): Promise<void>;
@@ -0,0 +1,51 @@
1
+ import { callService } from "./ajax.js";
2
+ import { openSitePage } from "./session.js";
3
+ import { MoodleError } from "./errors.js";
4
+ /**
5
+ * Runs one of the course editor's actions through its own service (ADR-004), as the editor does:
6
+ * ids of activities or sections, and a target section (`cm_move`: at its end; `section_add`,
7
+ * `section_move_after`: after it) or a target activity (`cm_move`: before it).
8
+ */
9
+ export async function editCourse(context, siteUrl, courseId, action, ids, target = {}) {
10
+ await callService(context, siteUrl, "core_courseformat_update_course", {
11
+ action,
12
+ courseid: courseId,
13
+ ids,
14
+ ...(target.sectionId ? { targetsectionid: target.sectionId } : {}),
15
+ ...(target.activityId ? { targetcmid: target.activityId } : {}),
16
+ });
17
+ }
18
+ // A course's format doesn't change while a program runs.
19
+ const formats = new Map();
20
+ /** The course format (topics, weeks…), a class of the course page's body: no service tells teachers. */
21
+ export async function courseFormat(context, siteUrl, courseId) {
22
+ const key = `${siteUrl}|${courseId}`;
23
+ const cached = formats.get(key);
24
+ if (cached)
25
+ return cached;
26
+ const page = await openSitePage(context, siteUrl, `course/view.php?id=${courseId}`);
27
+ try {
28
+ const classes = await page.evaluate(() => globalThis.document.body.className);
29
+ const format = classes
30
+ .split(" ")
31
+ .find((name) => name.startsWith("format-"))
32
+ ?.slice("format-".length);
33
+ if (!format)
34
+ throw new MoodleError(`Course ${courseId}'s format isn't on its page.`, "unexpected-page");
35
+ formats.set(key, format);
36
+ return format;
37
+ }
38
+ finally {
39
+ await page.close().catch(() => undefined);
40
+ }
41
+ }
42
+ /** Renames an activity, as the course page's in-place editor does. */
43
+ export async function renameActivity(context, siteUrl, activityId, name) {
44
+ await callService(context, siteUrl, "core_update_inplace_editable", { component: "core_course", itemtype: "activityname", itemid: activityId, value: name });
45
+ }
46
+ /** Renames a section through its course format's in-place editor. */
47
+ export async function renameSection(context, siteUrl, courseId, sectionId, name) {
48
+ const format = await courseFormat(context, siteUrl, courseId);
49
+ await callService(context, siteUrl, "core_update_inplace_editable", { component: `format_${format}`, itemtype: "sectionname", itemid: sectionId, value: name });
50
+ }
51
+ //# sourceMappingURL=editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../src/core/editor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * What went wrong, stable across releases: match errors by `code` (or by class), never by message,
3
+ * whose wording may change. Each error class has its own code; `MoodleError` itself takes one
4
+ * of the generic ones.
5
+ */
6
+ export type MoodleErrorCode = "invalid-input" | "not-found" | "not-available" | "outside-site" | "unexpected-page" | "logout-failed" | "chromium-install-failed" | "moodle-url" | "browser-not-found" | "browser-downloading" | "no-display" | "not-logged-in" | "login-timeout" | "login-window-closed" | "moodle-service" | "form" | "activity-settings" | "not-viewable" | "not-an-assignment" | "grading" | "submission" | "calendar" | "completion" | "course" | "not-a-forum" | "gradebook" | "no-grade-report" | "not-an-h5p-activity" | "scorm" | "lesson" | "message" | "no-participants" | "question-bank" | "quiz" | "choice" | "survey";
7
+ /** Every error the driver throws on purpose: one class to catch, a stable `code` to tell them apart. */
8
+ export declare class MoodleError extends Error {
9
+ name: string;
10
+ readonly code: MoodleErrorCode;
11
+ constructor(message: string, code: MoodleErrorCode);
12
+ }