@falkenslab/moodle-driver 0.0.0-stage → 0.3.1

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 (297) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -2
  3. package/dist/areas/activities/build.d.ts +98 -0
  4. package/dist/areas/activities/build.js +246 -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/site/info.d.ts +25 -0
  73. package/dist/areas/site/info.js +45 -0
  74. package/dist/areas/site/info.js.map +1 -0
  75. package/dist/areas/site/users.d.ts +56 -0
  76. package/dist/areas/site/users.js +89 -0
  77. package/dist/areas/site/users.js.map +1 -0
  78. package/dist/areas/surveys/choice.d.ts +38 -0
  79. package/dist/areas/surveys/choice.js +105 -0
  80. package/dist/areas/surveys/choice.js.map +1 -0
  81. package/dist/areas/surveys/surveys.d.ts +51 -0
  82. package/dist/areas/surveys/surveys.js +201 -0
  83. package/dist/areas/surveys/surveys.js.map +1 -0
  84. package/dist/browser/chromium.d.ts +15 -0
  85. package/dist/browser/chromium.js +53 -0
  86. package/dist/browser/chromium.js.map +1 -0
  87. package/dist/browser/cookies.d.ts +11 -0
  88. package/dist/browser/cookies.js +31 -0
  89. package/dist/browser/cookies.js.map +1 -0
  90. package/dist/browser/manager.d.ts +57 -0
  91. package/dist/browser/manager.js +177 -0
  92. package/dist/browser/manager.js.map +1 -0
  93. package/dist/browser.d.ts +53 -0
  94. package/dist/browser.js +167 -0
  95. package/dist/browser.js.map +1 -0
  96. package/dist/categories.d.ts +28 -0
  97. package/dist/categories.js +222 -0
  98. package/dist/categories.js.map +1 -0
  99. package/dist/chromiumInstaller.d.ts +15 -0
  100. package/dist/chromiumInstaller.js +52 -0
  101. package/dist/chromiumInstaller.js.map +1 -0
  102. package/dist/cli/args.d.ts +33 -0
  103. package/dist/cli/args.js +194 -0
  104. package/dist/cli/args.js.map +1 -0
  105. package/dist/cli/commands.generated.d.ts +4 -0
  106. package/dist/cli/commands.generated.js +2203 -0
  107. package/dist/cli/commands.generated.js.map +1 -0
  108. package/dist/cli/config.d.ts +46 -0
  109. package/dist/cli/config.js +107 -0
  110. package/dist/cli/config.js.map +1 -0
  111. package/dist/cli/main.d.ts +2 -0
  112. package/dist/cli/main.js +19 -0
  113. package/dist/cli/main.js.map +1 -0
  114. package/dist/cli/output.d.ts +4 -0
  115. package/dist/cli/output.js +71 -0
  116. package/dist/cli/output.js.map +1 -0
  117. package/dist/cli/run.d.ts +15 -0
  118. package/dist/cli/run.js +194 -0
  119. package/dist/cli/run.js.map +1 -0
  120. package/dist/cli/spec.d.ts +42 -0
  121. package/dist/cli/spec.js +4 -0
  122. package/dist/cli/spec.js.map +1 -0
  123. package/dist/client.d.ts +217 -0
  124. package/dist/client.js +179 -0
  125. package/dist/client.js.map +1 -0
  126. package/dist/core/ajax.d.ts +25 -0
  127. package/dist/core/ajax.js +85 -0
  128. package/dist/core/ajax.js.map +1 -0
  129. package/dist/core/editor.d.ts +18 -0
  130. package/dist/core/editor.js +51 -0
  131. package/dist/core/editor.js.map +1 -0
  132. package/dist/core/errors.d.ts +12 -0
  133. package/dist/core/errors.js +10 -0
  134. package/dist/core/errors.js.map +1 -0
  135. package/dist/core/files.d.ts +16 -0
  136. package/dist/core/files.js +58 -0
  137. package/dist/core/files.js.map +1 -0
  138. package/dist/core/forms.d.ts +45 -0
  139. package/dist/core/forms.js +200 -0
  140. package/dist/core/forms.js.map +1 -0
  141. package/dist/core/http.d.ts +18 -0
  142. package/dist/core/http.js +22 -0
  143. package/dist/core/http.js.map +1 -0
  144. package/dist/core/inPage.d.ts +8 -0
  145. package/dist/core/inPage.js +10 -0
  146. package/dist/core/inPage.js.map +1 -0
  147. package/dist/core/login.d.ts +40 -0
  148. package/dist/core/login.js +83 -0
  149. package/dist/core/login.js.map +1 -0
  150. package/dist/core/pace.d.ts +4 -0
  151. package/dist/core/pace.js +21 -0
  152. package/dist/core/pace.js.map +1 -0
  153. package/dist/core/session.d.ts +55 -0
  154. package/dist/core/session.js +157 -0
  155. package/dist/core/session.js.map +1 -0
  156. package/dist/core/site.d.ts +8 -0
  157. package/dist/core/site.js +36 -0
  158. package/dist/core/site.js.map +1 -0
  159. package/dist/core/text.d.ts +21 -0
  160. package/dist/core/text.js +113 -0
  161. package/dist/core/text.js.map +1 -0
  162. package/dist/home.d.ts +19 -0
  163. package/dist/home.js +54 -0
  164. package/dist/home.js.map +1 -0
  165. package/dist/index.d.ts +40 -0
  166. package/dist/index.js +51 -0
  167. package/dist/index.js.map +1 -0
  168. package/dist/internals.d.ts +11 -0
  169. package/dist/internals.js +15 -0
  170. package/dist/internals.js.map +1 -0
  171. package/dist/moodle/activities.d.ts +94 -0
  172. package/dist/moodle/activities.js +240 -0
  173. package/dist/moodle/activities.js.map +1 -0
  174. package/dist/moodle/ajax.d.ts +22 -0
  175. package/dist/moodle/ajax.js +91 -0
  176. package/dist/moodle/ajax.js.map +1 -0
  177. package/dist/moodle/assign.d.ts +65 -0
  178. package/dist/moodle/assign.js +162 -0
  179. package/dist/moodle/assign.js.map +1 -0
  180. package/dist/moodle/calendar.d.ts +41 -0
  181. package/dist/moodle/calendar.js +80 -0
  182. package/dist/moodle/calendar.js.map +1 -0
  183. package/dist/moodle/choice.d.ts +33 -0
  184. package/dist/moodle/choice.js +100 -0
  185. package/dist/moodle/choice.js.map +1 -0
  186. package/dist/moodle/completion.d.ts +48 -0
  187. package/dist/moodle/completion.js +108 -0
  188. package/dist/moodle/completion.js.map +1 -0
  189. package/dist/moodle/content.d.ts +43 -0
  190. package/dist/moodle/content.js +105 -0
  191. package/dist/moodle/content.js.map +1 -0
  192. package/dist/moodle/course.d.ts +51 -0
  193. package/dist/moodle/course.js +45 -0
  194. package/dist/moodle/course.js.map +1 -0
  195. package/dist/moodle/courses.d.ts +57 -0
  196. package/dist/moodle/courses.js +70 -0
  197. package/dist/moodle/courses.js.map +1 -0
  198. package/dist/moodle/editor.d.ts +18 -0
  199. package/dist/moodle/editor.js +50 -0
  200. package/dist/moodle/editor.js.map +1 -0
  201. package/dist/moodle/files.d.ts +16 -0
  202. package/dist/moodle/files.js +57 -0
  203. package/dist/moodle/files.js.map +1 -0
  204. package/dist/moodle/forms.d.ts +44 -0
  205. package/dist/moodle/forms.js +199 -0
  206. package/dist/moodle/forms.js.map +1 -0
  207. package/dist/moodle/forum.d.ts +55 -0
  208. package/dist/moodle/forum.js +115 -0
  209. package/dist/moodle/forum.js.map +1 -0
  210. package/dist/moodle/forumPosts.d.ts +83 -0
  211. package/dist/moodle/forumPosts.js +113 -0
  212. package/dist/moodle/forumPosts.js.map +1 -0
  213. package/dist/moodle/gradebook.d.ts +102 -0
  214. package/dist/moodle/gradebook.js +246 -0
  215. package/dist/moodle/gradebook.js.map +1 -0
  216. package/dist/moodle/grades.d.ts +24 -0
  217. package/dist/moodle/grades.js +67 -0
  218. package/dist/moodle/grades.js.map +1 -0
  219. package/dist/moodle/grading.d.ts +92 -0
  220. package/dist/moodle/grading.js +161 -0
  221. package/dist/moodle/grading.js.map +1 -0
  222. package/dist/moodle/h5p.d.ts +31 -0
  223. package/dist/moodle/h5p.js +100 -0
  224. package/dist/moodle/h5p.js.map +1 -0
  225. package/dist/moodle/inPage.d.ts +8 -0
  226. package/dist/moodle/inPage.js +10 -0
  227. package/dist/moodle/inPage.js.map +1 -0
  228. package/dist/moodle/lesson.d.ts +57 -0
  229. package/dist/moodle/lesson.js +140 -0
  230. package/dist/moodle/lesson.js.map +1 -0
  231. package/dist/moodle/login.d.ts +37 -0
  232. package/dist/moodle/login.js +77 -0
  233. package/dist/moodle/login.js.map +1 -0
  234. package/dist/moodle/messages.d.ts +66 -0
  235. package/dist/moodle/messages.js +80 -0
  236. package/dist/moodle/messages.js.map +1 -0
  237. package/dist/moodle/overview.d.ts +83 -0
  238. package/dist/moodle/overview.js +137 -0
  239. package/dist/moodle/overview.js.map +1 -0
  240. package/dist/moodle/pace.d.ts +4 -0
  241. package/dist/moodle/pace.js +19 -0
  242. package/dist/moodle/pace.js.map +1 -0
  243. package/dist/moodle/participants.d.ts +55 -0
  244. package/dist/moodle/participants.js +131 -0
  245. package/dist/moodle/participants.js.map +1 -0
  246. package/dist/moodle/questionBank.d.ts +81 -0
  247. package/dist/moodle/questionBank.js +235 -0
  248. package/dist/moodle/questionBank.js.map +1 -0
  249. package/dist/moodle/quiz.d.ts +117 -0
  250. package/dist/moodle/quiz.js +291 -0
  251. package/dist/moodle/quiz.js.map +1 -0
  252. package/dist/moodle/quizResults.d.ts +36 -0
  253. package/dist/moodle/quizResults.js +93 -0
  254. package/dist/moodle/quizResults.js.map +1 -0
  255. package/dist/moodle/quizStructure.d.ts +42 -0
  256. package/dist/moodle/quizStructure.js +100 -0
  257. package/dist/moodle/quizStructure.js.map +1 -0
  258. package/dist/moodle/session.d.ts +39 -0
  259. package/dist/moodle/session.js +99 -0
  260. package/dist/moodle/session.js.map +1 -0
  261. package/dist/moodle/site.d.ts +8 -0
  262. package/dist/moodle/site.js +36 -0
  263. package/dist/moodle/site.js.map +1 -0
  264. package/dist/moodle/siteInfo.d.ts +25 -0
  265. package/dist/moodle/siteInfo.js +45 -0
  266. package/dist/moodle/siteInfo.js.map +1 -0
  267. package/dist/moodle/structure.d.ts +94 -0
  268. package/dist/moodle/structure.js +103 -0
  269. package/dist/moodle/structure.js.map +1 -0
  270. package/dist/moodle/submission.d.ts +48 -0
  271. package/dist/moodle/submission.js +109 -0
  272. package/dist/moodle/submission.js.map +1 -0
  273. package/dist/moodle/survey.d.ts +47 -0
  274. package/dist/moodle/survey.js +197 -0
  275. package/dist/moodle/survey.js.map +1 -0
  276. package/dist/moodle/text.d.ts +21 -0
  277. package/dist/moodle/text.js +113 -0
  278. package/dist/moodle/text.js.map +1 -0
  279. package/dist/moodle/user.d.ts +54 -0
  280. package/dist/moodle/user.js +78 -0
  281. package/dist/moodle/user.js.map +1 -0
  282. package/dist/options.d.ts +30 -0
  283. package/dist/options.js +35 -0
  284. package/dist/options.js.map +1 -0
  285. package/dist/sessionCookies.d.ts +11 -0
  286. package/dist/sessionCookies.js +31 -0
  287. package/dist/sessionCookies.js.map +1 -0
  288. package/dist/testing/fakeMoodle.d.ts +55 -0
  289. package/dist/testing/fakeMoodle.js +103 -0
  290. package/dist/testing/fakeMoodle.js.map +1 -0
  291. package/dist/testing/gradingPanel.d.ts +6 -0
  292. package/dist/testing/gradingPanel.js +22 -0
  293. package/dist/testing/gradingPanel.js.map +1 -0
  294. package/dist/testing/index.d.ts +5 -0
  295. package/dist/testing/index.js +18 -0
  296. package/dist/testing/index.js.map +1 -0
  297. package/package.json +77 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surveys.js","sourceRoot":"","sources":["../../../src/areas/surveys/surveys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ export type InstallChromium = () => Promise<void>;
3
+ /**
4
+ * Starts a process that `killTree` can end with everything it starts: on Linux and macOS as the
5
+ * leader of its own process group; on Windows `taskkill /T` walks the tree, and no console opens.
6
+ */
7
+ export declare function spawnTree(command: string, args: string[]): ChildProcess;
8
+ /** Ends a process started by `spawnTree` and its children, at once; nothing if it's gone. */
9
+ export declare function killTree(pid: number): void;
10
+ /**
11
+ * Downloads the Chromium this `playwright-core` expects with its own CLI (ADR-001), into
12
+ * `PLAYWRIGHT_BROWSERS_PATH` when set, else the user's `ms-playwright` cache. The CLI is in
13
+ * `node_modules`, where `playwright-core` is (a peer dependency).
14
+ */
15
+ export declare const installChromium: InstallChromium;
@@ -0,0 +1,53 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ import { MoodleError } from "../core/errors.js";
5
+ /**
6
+ * Starts a process that `killTree` can end with everything it starts: on Linux and macOS as the
7
+ * leader of its own process group; on Windows `taskkill /T` walks the tree, and no console opens.
8
+ */
9
+ export function spawnTree(command, args) {
10
+ return spawn(command, args, { stdio: ["ignore", "pipe", "pipe"], detached: process.platform !== "win32", windowsHide: true });
11
+ }
12
+ /** Ends a process started by `spawnTree` and its children, at once; nothing if it's gone. */
13
+ export function killTree(pid) {
14
+ try {
15
+ if (process.platform === "win32")
16
+ spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
17
+ else
18
+ process.kill(-pid, "SIGKILL");
19
+ }
20
+ catch {
21
+ // Already gone.
22
+ }
23
+ }
24
+ /**
25
+ * Downloads the Chromium this `playwright-core` expects with its own CLI (ADR-001), into
26
+ * `PLAYWRIGHT_BROWSERS_PATH` when set, else the user's `ms-playwright` cache. The CLI is in
27
+ * `node_modules`, where `playwright-core` is (a peer dependency).
28
+ */
29
+ export const installChromium = () => new Promise((resolve, reject) => {
30
+ const cli = path.join(path.dirname(createRequire(import.meta.url).resolve("playwright-core/package.json")), "cli.js");
31
+ // --no-shell: the driver launches full Chromium headless too (channel "chromium").
32
+ // --no-remove: the cache is shared, and other installations' browsers aren't ours to remove.
33
+ const child = spawnTree(process.execPath, [cli, "install", "chromium", "--no-shell", "--no-remove", "--no-progress"]);
34
+ // The CLI downloads from a child of its own: when the program exits, the whole tree goes with it,
35
+ // instead of downloading on with nobody to use it (a partial download is started over next time).
36
+ const stop = () => killTree(child.pid);
37
+ process.on("exit", stop);
38
+ // A program's stdout may be a protocol (an MCP server's): whatever the installer prints goes to stderr.
39
+ child.stdout.pipe(process.stderr, { end: false });
40
+ child.stderr.pipe(process.stderr, { end: false });
41
+ child.on("error", (error) => {
42
+ process.off("exit", stop);
43
+ reject(error);
44
+ });
45
+ child.on("exit", (code) => {
46
+ process.off("exit", stop);
47
+ if (code === 0)
48
+ resolve();
49
+ else
50
+ reject(new MoodleError(`Chromium's installer exited with code ${code}`, "chromium-install-failed"));
51
+ });
52
+ });
53
+ //# sourceMappingURL=chromium.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chromium.js","sourceRoot":"","sources":["../../src/browser/chromium.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAqB,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIhD;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAc;IACvD,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;AAChI,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,SAAS,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;;YAC9H,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAoB,GAAG,EAAE,CACnD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACtH,mFAAmF;IACnF,6FAA6F;IAC7F,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC,CAAC;IACtH,kGAAkG;IAClG,kGAAkG;IAClG,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAI,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzB,wGAAwG;IACxG,KAAK,CAAC,MAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,KAAK,CAAC,MAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC1B,IAAI,IAAI,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;;YACrB,MAAM,CAAC,IAAI,WAAW,CAAC,yCAAyC,IAAI,EAAE,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC3G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { BrowserContext } from "playwright-core";
2
+ /**
3
+ * Chromium drops session cookies (no expiry) when a persistent profile closes, and Moodle's
4
+ * `MoodleSession` is one (confirmed empirically, Edge and playwright-core 1.64, Moodle 5.2): the
5
+ * profile alone would forget the login on every restart. They are kept in this file inside the
6
+ * profile, as sensitive as the profile itself (ADR-003).
7
+ */
8
+ export declare const SESSION_COOKIES_FILE = "moodle-session.json";
9
+ export declare function saveSessionCookies(context: BrowserContext, profileDir: string): Promise<void>;
10
+ /** Puts back the session cookies saved last time; a missing or unreadable file means none. */
11
+ export declare function restoreSessionCookies(context: BrowserContext, profileDir: string): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ /**
4
+ * Chromium drops session cookies (no expiry) when a persistent profile closes, and Moodle's
5
+ * `MoodleSession` is one (confirmed empirically, Edge and playwright-core 1.64, Moodle 5.2): the
6
+ * profile alone would forget the login on every restart. They are kept in this file inside the
7
+ * profile, as sensitive as the profile itself (ADR-003).
8
+ */
9
+ export const SESSION_COOKIES_FILE = "moodle-session.json";
10
+ export async function saveSessionCookies(context, profileDir) {
11
+ const sessionCookies = (await context.cookies()).filter((cookie) => cookie.expires === -1);
12
+ await writeFile(path.join(profileDir, SESSION_COOKIES_FILE), JSON.stringify(sessionCookies), { mode: 0o600 });
13
+ }
14
+ /** Puts back the session cookies saved last time; a missing or unreadable file means none. */
15
+ export async function restoreSessionCookies(context, profileDir) {
16
+ let cookies;
17
+ try {
18
+ cookies = JSON.parse(await readFile(path.join(profileDir, SESSION_COOKIES_FILE), "utf8"));
19
+ }
20
+ catch {
21
+ return;
22
+ }
23
+ if (!Array.isArray(cookies) || cookies.length === 0)
24
+ return;
25
+ // Cookies the browser kept itself are newer than the file's.
26
+ const kept = new Set((await context.cookies()).map((c) => `${c.name}|${c.domain}|${c.path}`));
27
+ const missing = cookies.filter((c) => !kept.has(`${c.name}|${c.domain}|${c.path}`));
28
+ if (missing.length > 0)
29
+ await context.addCookies(missing).catch(() => undefined);
30
+ }
31
+ //# sourceMappingURL=cookies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.js","sourceRoot":"","sources":["../../src/browser/cookies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAuB,EAAE,UAAkB;IAClF,MAAM,cAAc,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChH,CAAC;AAED,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAuB,EAAE,UAAkB;IACrF,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,oBAAoB,CAAC,EAAE,MAAM,CAAC,CAAa,CAAC;IACxG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC5D,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9F,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACpF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { chromium, type BrowserContext, type Page } from "playwright-core";
2
+ import { type InstallChromium } from "./chromium.js";
3
+ import { type BrowserOptions, type Channel } from "../options.js";
4
+ import { MoodleError } from "../core/errors.js";
5
+ type LaunchPersistentContext = typeof chromium.launchPersistentContext;
6
+ export interface ContextOptions {
7
+ /** A visible window, whatever the options say (logging in by hand). */
8
+ headed?: boolean;
9
+ }
10
+ /** The browser's single persistent context, opened on first use (ADR-002). */
11
+ export interface BrowserManager {
12
+ /**
13
+ * The open context, launching it if needed. A headed request relaunches a headless context with
14
+ * a window; a headless request reuses a headed one rather than closing a window the person may be using.
15
+ */
16
+ context(options?: ContextOptions): Promise<BrowserContext>;
17
+ /** The channel of the open context, or `undefined` while none is open. */
18
+ openChannel(): Channel | undefined;
19
+ /** Whether Chromium is being downloaded, or the last download failed (ADR-001). */
20
+ chromiumDownload(): "downloading" | "failed" | undefined;
21
+ /** Whether the browser shows a window now: what `setVisible` asked for, else the options. */
22
+ visible(): boolean;
23
+ /**
24
+ * Shows the browser (relaunching it with a window now, session kept) and follows the pages functions open
25
+ * in it, or hides it (closing the window; the next call runs headless). ADR-007.
26
+ */
27
+ setVisible(visible: boolean): Promise<void>;
28
+ /** While following, brings `url` (a site page) to the front of the window; best effort, never throws. */
29
+ show(url: string): Promise<void>;
30
+ /** The one working tab a program drives itself (ADR-007), the same one following shows; opens the browser if needed. */
31
+ tab(): Promise<Page>;
32
+ /** Saves the session cookies of the open context, if any (ADR-003). */
33
+ saveSession(): Promise<void>;
34
+ close(): Promise<void>;
35
+ }
36
+ /** No installed browser could be launched, and Chromium can't be downloaded (ADR-001). */
37
+ export declare class BrowserNotFoundError extends MoodleError {
38
+ name: string;
39
+ constructor(message: string);
40
+ }
41
+ /** No browser yet: Chromium is downloading in the background, and the call should be retried later. */
42
+ export declare class BrowserDownloadingError extends MoodleError {
43
+ name: string;
44
+ constructor(message: string);
45
+ }
46
+ /** A window was asked for where there's no screen to show it (a container, a server). */
47
+ export declare class NoDisplayError extends MoodleError {
48
+ name: string;
49
+ constructor(message: string);
50
+ }
51
+ /**
52
+ * Whether a window can be shown. On Linux it needs an X or Wayland display; without one (Docker, a
53
+ * server) the driver refuses rather than trying, so it never reaches a display it wasn't given.
54
+ */
55
+ export declare function canShowWindow(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
56
+ export declare function createBrowserManager(config: BrowserOptions, launch?: LaunchPersistentContext, install?: InstallChromium, windowsPossible?: () => boolean): BrowserManager;
57
+ export {};
@@ -0,0 +1,177 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { chromium } from "playwright-core";
3
+ import { installChromium } from "./chromium.js";
4
+ import { SYSTEM_CHANNELS } from "../options.js";
5
+ import { followPages } from "../core/session.js";
6
+ import { restoreSessionCookies, saveSessionCookies } from "./cookies.js";
7
+ import { MoodleError } from "../core/errors.js";
8
+ /** No installed browser could be launched, and Chromium can't be downloaded (ADR-001). */
9
+ export class BrowserNotFoundError extends MoodleError {
10
+ name = "BrowserNotFoundError";
11
+ constructor(message) {
12
+ super(message, "browser-not-found");
13
+ }
14
+ }
15
+ /** No browser yet: Chromium is downloading in the background, and the call should be retried later. */
16
+ export class BrowserDownloadingError extends MoodleError {
17
+ name = "BrowserDownloadingError";
18
+ constructor(message) {
19
+ super(message, "browser-downloading");
20
+ }
21
+ }
22
+ /** A window was asked for where there's no screen to show it (a container, a server). */
23
+ export class NoDisplayError extends MoodleError {
24
+ name = "NoDisplayError";
25
+ constructor(message) {
26
+ super(message, "no-display");
27
+ }
28
+ }
29
+ /**
30
+ * Whether a window can be shown. On Linux it needs an X or Wayland display; without one (Docker, a
31
+ * server) the driver refuses rather than trying, so it never reaches a display it wasn't given.
32
+ */
33
+ export function canShowWindow(env = process.env, platform = process.platform) {
34
+ return platform !== "linux" || Boolean(env.DISPLAY || env.WAYLAND_DISPLAY);
35
+ }
36
+ // Playwright's message when a channel isn't installed: "Chromium distribution 'msedge' is not found",
37
+ // with " at <path>" only when it knows where to look (playwright-core 1.64).
38
+ const NOT_INSTALLED = /distribution '[^']+' is not (found|supported)|Executable doesn't exist/i;
39
+ // Moodle pages can take long, above all the first ones after the site starts.
40
+ const NAVIGATION_TIMEOUT_MS = 60_000;
41
+ export function createBrowserManager(config, launch = chromium.launchPersistentContext.bind(chromium), install = installChromium, windowsPossible = canShowWindow) {
42
+ let open;
43
+ // What `setVisible` asked for, over the options; following goes with it.
44
+ let shown;
45
+ let followTab;
46
+ // The download runs in the background, outside the queue: it takes minutes, longer than some
47
+ // callers wait, so calls meanwhile answer at once that it's downloading.
48
+ let download;
49
+ let downloadFailure;
50
+ function startDownload() {
51
+ const retry = downloadFailure ? ` The previous download failed (${downloadFailure}); trying again.` : "";
52
+ downloadFailure = undefined;
53
+ download ??= install().then(() => {
54
+ download = undefined;
55
+ }, (error) => {
56
+ download = undefined;
57
+ downloadFailure = error.message ?? String(error);
58
+ });
59
+ return downloading(retry);
60
+ }
61
+ function downloading(extra = "") {
62
+ return new BrowserDownloadingError(`${config.channel === "chromium" ? "Chromium isn't downloaded yet" : "Neither Microsoft Edge nor Google Chrome is available"}, so it's being downloaded (about 180 MB, into PLAYWRIGHT_BROWSERS_PATH or the user's ms-playwright cache).${extra} Try again in a minute or two.`);
63
+ }
64
+ // One operation at a time: two launches on the same profile would fail.
65
+ let queue = Promise.resolve();
66
+ function exclusive(operation) {
67
+ const result = queue.then(operation, operation);
68
+ queue = result.catch(() => undefined);
69
+ return result;
70
+ }
71
+ async function launchFirstAvailable(headed) {
72
+ await mkdir(config.profileDir, { recursive: true });
73
+ const channels = config.channel ? [config.channel] : [...SYSTEM_CHANNELS, ...(config.downloadBrowser ? ["chromium"] : [])];
74
+ const missing = [];
75
+ for (const channel of channels) {
76
+ if (channel === "chromium" && download)
77
+ throw downloading();
78
+ let context;
79
+ try {
80
+ // A window keeps its own size; a fixed viewport would leave it half empty.
81
+ context = await launch(config.profileDir, { channel, headless: !headed, ...(headed ? { viewport: null } : {}) });
82
+ }
83
+ catch (error) {
84
+ const message = error.message ?? String(error);
85
+ if (!NOT_INSTALLED.test(message))
86
+ throw error;
87
+ if (channel === "chromium" && config.downloadBrowser)
88
+ throw startDownload();
89
+ missing.push(channel);
90
+ continue;
91
+ }
92
+ context.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT_MS);
93
+ followPages(context, (url) => manager.show(url));
94
+ await restoreSessionCookies(context, config.profileDir);
95
+ const opened = { context, channel, headed };
96
+ // The person may close the window: the next call opens the browser again, headless if they had
97
+ // asked to see it (closing it says they're done watching).
98
+ context.on("close", () => {
99
+ if (open !== opened)
100
+ return;
101
+ open = undefined;
102
+ if (opened.headed && shown)
103
+ shown = false;
104
+ });
105
+ return opened;
106
+ }
107
+ throw new BrowserNotFoundError(`No browser found (tried ${missing.join(", ")}). Install Microsoft Edge or Google Chrome${config.downloadBrowser ? "" : ", or allow downloading Chromium (downloadBrowser)"}, or choose another channel.`);
108
+ }
109
+ /** The working tab in `context`: the one already in use, else the window's first empty tab, else a new one. */
110
+ async function workTab(context) {
111
+ if (!followTab || followTab.isClosed())
112
+ followTab = context.pages().find((p) => p.url() === "about:blank") ?? (await context.newPage());
113
+ return followTab;
114
+ }
115
+ async function closeOpen() {
116
+ const current = open;
117
+ open = undefined;
118
+ followTab = undefined;
119
+ if (!current)
120
+ return;
121
+ await saveSessionCookies(current.context, config.profileDir).catch(() => undefined);
122
+ await current.context.close().catch(() => undefined);
123
+ }
124
+ const manager = {
125
+ context({ headed = false } = {}) {
126
+ return exclusive(async () => {
127
+ const wantHeaded = headed || (shown ?? !config.headless);
128
+ if (open && (open.headed || !wantHeaded))
129
+ return open.context;
130
+ if (wantHeaded && !windowsPossible()) {
131
+ throw new NoDisplayError(`There's no screen to show a browser window here (no DISPLAY or WAYLAND_DISPLAY), so ${headed ? "logging in by hand isn't possible" : "a headed browser can't open"}. Run headless with a profile already logged in, or where there's a screen.`);
132
+ }
133
+ await closeOpen();
134
+ open = await launchFirstAvailable(wantHeaded);
135
+ return open.context;
136
+ });
137
+ },
138
+ visible: () => shown ?? !config.headless,
139
+ setVisible: (visible) => exclusive(async () => {
140
+ if (visible && !windowsPossible()) {
141
+ throw new NoDisplayError("There's no screen to show a browser window here (no DISPLAY or WAYLAND_DISPLAY). The browser keeps working headless.");
142
+ }
143
+ shown = visible;
144
+ if (visible && !open?.headed) {
145
+ await closeOpen();
146
+ open = await launchFirstAvailable(true);
147
+ }
148
+ else if (!visible && open?.headed) {
149
+ await closeOpen();
150
+ }
151
+ }),
152
+ async show(url) {
153
+ const current = open;
154
+ if (!shown || !current?.headed)
155
+ return;
156
+ try {
157
+ const tab = await workTab(current.context);
158
+ if (tab.url() !== url)
159
+ await tab.goto(url, { waitUntil: "domcontentloaded" });
160
+ await tab.bringToFront();
161
+ }
162
+ catch {
163
+ // Following is a courtesy: a page that doesn't load never changes a function's result.
164
+ }
165
+ },
166
+ tab: async () => workTab(await manager.context()),
167
+ openChannel: () => open?.channel,
168
+ chromiumDownload: () => (download ? "downloading" : downloadFailure ? "failed" : undefined),
169
+ saveSession: () => exclusive(async () => {
170
+ if (open)
171
+ await saveSessionCookies(open.context, config.profileDir);
172
+ }),
173
+ close: () => exclusive(closeOpen),
174
+ };
175
+ return manager;
176
+ }
177
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/browser/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { chromium, type BrowserContext, type Page } from "playwright-core";
2
+ import { type InstallChromium } from "./chromiumInstaller.js";
3
+ import { type BrowserOptions, type Channel } from "./options.js";
4
+ type LaunchPersistentContext = typeof chromium.launchPersistentContext;
5
+ export interface ContextOptions {
6
+ /** A visible window, whatever the options say (logging in by hand). */
7
+ headed?: boolean;
8
+ }
9
+ /** The browser's single persistent context, opened on first use (ADR-002). */
10
+ export interface BrowserManager {
11
+ /**
12
+ * The open context, launching it if needed. A headed request relaunches a headless context with
13
+ * a window; a headless request reuses a headed one rather than closing a window the person may be using.
14
+ */
15
+ context(options?: ContextOptions): Promise<BrowserContext>;
16
+ /** The channel of the open context, or `undefined` while none is open. */
17
+ openChannel(): Channel | undefined;
18
+ /** Whether Chromium is being downloaded, or the last download failed (ADR-001). */
19
+ chromiumDownload(): "downloading" | "failed" | undefined;
20
+ /** Whether the browser shows a window now: what `setVisible` asked for, else the options. */
21
+ visible(): boolean;
22
+ /**
23
+ * Shows the browser (relaunching it with a window now, session kept) and follows the pages functions open
24
+ * in it, or hides it (closing the window; the next call runs headless). ADR-007.
25
+ */
26
+ setVisible(visible: boolean): Promise<void>;
27
+ /** While following, brings `url` (a site page) to the front of the window; best effort, never throws. */
28
+ show(url: string): Promise<void>;
29
+ /** The one working tab a program drives itself (ADR-007), the same one following shows; opens the browser if needed. */
30
+ tab(): Promise<Page>;
31
+ /** Saves the session cookies of the open context, if any (ADR-003). */
32
+ saveSession(): Promise<void>;
33
+ close(): Promise<void>;
34
+ }
35
+ /** No installed browser could be launched, and Chromium can't be downloaded (ADR-001). */
36
+ export declare class BrowserNotFoundError extends Error {
37
+ name: string;
38
+ }
39
+ /** No browser yet: Chromium is downloading in the background, and the call should be retried later. */
40
+ export declare class BrowserDownloadingError extends Error {
41
+ name: string;
42
+ }
43
+ /** A window was asked for where there's no screen to show it (a container, a server). */
44
+ export declare class NoDisplayError extends Error {
45
+ name: string;
46
+ }
47
+ /**
48
+ * Whether a window can be shown. On Linux it needs an X or Wayland display; without one (Docker, a
49
+ * server) the driver refuses rather than trying, so it never reaches a display it wasn't given.
50
+ */
51
+ export declare function canShowWindow(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): boolean;
52
+ export declare function createBrowserManager(config: BrowserOptions, launch?: LaunchPersistentContext, install?: InstallChromium, windowsPossible?: () => boolean): BrowserManager;
53
+ export {};
@@ -0,0 +1,167 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { chromium } from "playwright-core";
3
+ import { installChromium } from "./chromiumInstaller.js";
4
+ import { SYSTEM_CHANNELS } from "./options.js";
5
+ import { followPages } from "./moodle/session.js";
6
+ import { restoreSessionCookies, saveSessionCookies } from "./sessionCookies.js";
7
+ /** No installed browser could be launched, and Chromium can't be downloaded (ADR-001). */
8
+ export class BrowserNotFoundError extends Error {
9
+ name = "BrowserNotFoundError";
10
+ }
11
+ /** No browser yet: Chromium is downloading in the background, and the call should be retried later. */
12
+ export class BrowserDownloadingError extends Error {
13
+ name = "BrowserDownloadingError";
14
+ }
15
+ /** A window was asked for where there's no screen to show it (a container, a server). */
16
+ export class NoDisplayError extends Error {
17
+ name = "NoDisplayError";
18
+ }
19
+ /**
20
+ * Whether a window can be shown. On Linux it needs an X or Wayland display; without one (Docker, a
21
+ * server) the driver refuses rather than trying, so it never reaches a display it wasn't given.
22
+ */
23
+ export function canShowWindow(env = process.env, platform = process.platform) {
24
+ return platform !== "linux" || Boolean(env.DISPLAY || env.WAYLAND_DISPLAY);
25
+ }
26
+ // Playwright's message when a channel isn't installed: "Chromium distribution 'msedge' is not found",
27
+ // with " at <path>" only when it knows where to look (playwright-core 1.64).
28
+ const NOT_INSTALLED = /distribution '[^']+' is not (found|supported)|Executable doesn't exist/i;
29
+ // Moodle pages can take long, above all the first ones after the site starts.
30
+ const NAVIGATION_TIMEOUT_MS = 60_000;
31
+ export function createBrowserManager(config, launch = chromium.launchPersistentContext.bind(chromium), install = installChromium, windowsPossible = canShowWindow) {
32
+ let open;
33
+ // What `setVisible` asked for, over the options; following goes with it.
34
+ let shown;
35
+ let followTab;
36
+ // The download runs in the background, outside the queue: it takes minutes, longer than some
37
+ // callers wait, so calls meanwhile answer at once that it's downloading.
38
+ let download;
39
+ let downloadFailure;
40
+ function startDownload() {
41
+ const retry = downloadFailure ? ` The previous download failed (${downloadFailure}); trying again.` : "";
42
+ downloadFailure = undefined;
43
+ download ??= install().then(() => {
44
+ download = undefined;
45
+ }, (error) => {
46
+ download = undefined;
47
+ downloadFailure = error.message ?? String(error);
48
+ });
49
+ return downloading(retry);
50
+ }
51
+ function downloading(extra = "") {
52
+ return new BrowserDownloadingError(`${config.channel === "chromium" ? "Chromium isn't downloaded yet" : "Neither Microsoft Edge nor Google Chrome is available"}, so it's being downloaded (about 180 MB, into PLAYWRIGHT_BROWSERS_PATH or the user's ms-playwright cache).${extra} Try again in a minute or two.`);
53
+ }
54
+ // One operation at a time: two launches on the same profile would fail.
55
+ let queue = Promise.resolve();
56
+ function exclusive(operation) {
57
+ const result = queue.then(operation, operation);
58
+ queue = result.catch(() => undefined);
59
+ return result;
60
+ }
61
+ async function launchFirstAvailable(headed) {
62
+ await mkdir(config.profileDir, { recursive: true });
63
+ const channels = config.channel ? [config.channel] : [...SYSTEM_CHANNELS, ...(config.downloadBrowser ? ["chromium"] : [])];
64
+ const missing = [];
65
+ for (const channel of channels) {
66
+ if (channel === "chromium" && download)
67
+ throw downloading();
68
+ let context;
69
+ try {
70
+ // A window keeps its own size; a fixed viewport would leave it half empty.
71
+ context = await launch(config.profileDir, { channel, headless: !headed, ...(headed ? { viewport: null } : {}) });
72
+ }
73
+ catch (error) {
74
+ const message = error.message ?? String(error);
75
+ if (!NOT_INSTALLED.test(message))
76
+ throw error;
77
+ if (channel === "chromium" && config.downloadBrowser)
78
+ throw startDownload();
79
+ missing.push(channel);
80
+ continue;
81
+ }
82
+ context.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT_MS);
83
+ followPages(context, (url) => manager.show(url));
84
+ await restoreSessionCookies(context, config.profileDir);
85
+ const opened = { context, channel, headed };
86
+ // The person may close the window: the next call opens the browser again, headless if they had
87
+ // asked to see it (closing it says they're done watching).
88
+ context.on("close", () => {
89
+ if (open !== opened)
90
+ return;
91
+ open = undefined;
92
+ if (opened.headed && shown)
93
+ shown = false;
94
+ });
95
+ return opened;
96
+ }
97
+ throw new BrowserNotFoundError(`No browser found (tried ${missing.join(", ")}). Install Microsoft Edge or Google Chrome${config.downloadBrowser ? "" : ", or allow downloading Chromium (downloadBrowser)"}, or choose another channel.`);
98
+ }
99
+ /** The working tab in `context`: the one already in use, else the window's first empty tab, else a new one. */
100
+ async function workTab(context) {
101
+ if (!followTab || followTab.isClosed())
102
+ followTab = context.pages().find((p) => p.url() === "about:blank") ?? (await context.newPage());
103
+ return followTab;
104
+ }
105
+ async function closeOpen() {
106
+ const current = open;
107
+ open = undefined;
108
+ followTab = undefined;
109
+ if (!current)
110
+ return;
111
+ await saveSessionCookies(current.context, config.profileDir).catch(() => undefined);
112
+ await current.context.close().catch(() => undefined);
113
+ }
114
+ const manager = {
115
+ context({ headed = false } = {}) {
116
+ return exclusive(async () => {
117
+ const wantHeaded = headed || (shown ?? !config.headless);
118
+ if (open && (open.headed || !wantHeaded))
119
+ return open.context;
120
+ if (wantHeaded && !windowsPossible()) {
121
+ throw new NoDisplayError(`There's no screen to show a browser window here (no DISPLAY or WAYLAND_DISPLAY), so ${headed ? "logging in by hand isn't possible" : "a headed browser can't open"}. Run headless with a profile already logged in, or where there's a screen.`);
122
+ }
123
+ await closeOpen();
124
+ open = await launchFirstAvailable(wantHeaded);
125
+ return open.context;
126
+ });
127
+ },
128
+ visible: () => shown ?? !config.headless,
129
+ setVisible: (visible) => exclusive(async () => {
130
+ if (visible && !windowsPossible()) {
131
+ throw new NoDisplayError("There's no screen to show a browser window here (no DISPLAY or WAYLAND_DISPLAY). The browser keeps working headless.");
132
+ }
133
+ shown = visible;
134
+ if (visible && !open?.headed) {
135
+ await closeOpen();
136
+ open = await launchFirstAvailable(true);
137
+ }
138
+ else if (!visible && open?.headed) {
139
+ await closeOpen();
140
+ }
141
+ }),
142
+ async show(url) {
143
+ const current = open;
144
+ if (!shown || !current?.headed)
145
+ return;
146
+ try {
147
+ const tab = await workTab(current.context);
148
+ if (tab.url() !== url)
149
+ await tab.goto(url, { waitUntil: "domcontentloaded" });
150
+ await tab.bringToFront();
151
+ }
152
+ catch {
153
+ // Following is a courtesy: a page that doesn't load never changes a function's result.
154
+ }
155
+ },
156
+ tab: async () => workTab(await manager.context()),
157
+ openChannel: () => open?.channel,
158
+ chromiumDownload: () => (download ? "downloading" : downloadFailure ? "failed" : undefined),
159
+ saveSession: () => exclusive(async () => {
160
+ if (open)
161
+ await saveSessionCookies(open.context, config.profileDir);
162
+ }),
163
+ close: () => exclusive(closeOpen),
164
+ };
165
+ return manager;
166
+ }
167
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"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"}