@learnorama/mozaik-sdk 0.12.3-staging.46.1 → 0.13.0-staging.48.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 (266) hide show
  1. package/README.md +25 -0
  2. package/dist/api/account.d.ts +1 -1
  3. package/dist/api/account.js.map +1 -1
  4. package/dist/api/admin-catalogue.d.ts +1 -1
  5. package/dist/api/admin-catalogue.js.map +1 -1
  6. package/dist/api/admin-consumption.d.ts +1 -1
  7. package/dist/api/admin-consumption.js.map +1 -1
  8. package/dist/api/admin-contracts.d.ts +1 -1
  9. package/dist/api/admin-contracts.js.map +1 -1
  10. package/dist/api/admin-desk.d.ts +1 -1
  11. package/dist/api/admin-desk.js.map +1 -1
  12. package/dist/api/admin-licenses.d.ts +1 -1
  13. package/dist/api/admin-licenses.js.map +1 -1
  14. package/dist/api/admin-partner-selections.d.ts +1 -1
  15. package/dist/api/admin-partner-selections.js.map +1 -1
  16. package/dist/api/admin-patrons.d.ts +1 -1
  17. package/dist/api/admin-patrons.js.map +1 -1
  18. package/dist/api/admin-reviews.d.ts +1 -1
  19. package/dist/api/admin-reviews.js.map +1 -1
  20. package/dist/api/admin-roles.d.ts +1 -1
  21. package/dist/api/admin-roles.js.map +1 -1
  22. package/dist/api/admin-support.d.ts +1 -1
  23. package/dist/api/admin-support.js.map +1 -1
  24. package/dist/api/admin-tenants.d.ts +1 -1
  25. package/dist/api/admin-tenants.js.map +1 -1
  26. package/dist/api/admin-tutoring.d.ts +1 -1
  27. package/dist/api/admin-tutoring.js.map +1 -1
  28. package/dist/api/auth.d.ts +1 -1
  29. package/dist/api/auth.js.map +1 -1
  30. package/dist/api/biblio-billing-webhooks.d.ts +18 -0
  31. package/dist/api/biblio-billing-webhooks.js +62 -0
  32. package/dist/api/biblio-billing-webhooks.js.map +1 -0
  33. package/dist/api/biblio-billing.d.ts +192 -0
  34. package/dist/api/biblio-billing.js +645 -0
  35. package/dist/api/biblio-billing.js.map +1 -0
  36. package/dist/api/biblio-catalogue.d.ts +1 -1
  37. package/dist/api/biblio-catalogue.js.map +1 -1
  38. package/dist/api/biblio-home.d.ts +1 -1
  39. package/dist/api/biblio-home.js.map +1 -1
  40. package/dist/api/biblio-learning-author-profiles.d.ts +108 -0
  41. package/dist/api/biblio-learning-author-profiles.js +331 -0
  42. package/dist/api/biblio-learning-author-profiles.js.map +1 -0
  43. package/dist/api/biblio-learning-authoring.d.ts +168 -0
  44. package/dist/api/biblio-learning-authoring.js +586 -0
  45. package/dist/api/biblio-learning-authoring.js.map +1 -0
  46. package/dist/api/biblio-learning-editorial.d.ts +54 -0
  47. package/dist/api/biblio-learning-editorial.js +149 -0
  48. package/dist/api/biblio-learning-editorial.js.map +1 -0
  49. package/dist/api/biblio-learning-feedback.d.ts +60 -0
  50. package/dist/api/biblio-learning-feedback.js +180 -0
  51. package/dist/api/biblio-learning-feedback.js.map +1 -0
  52. package/dist/api/biblio-learning-finance.d.ts +186 -0
  53. package/dist/api/biblio-learning-finance.js +622 -0
  54. package/dist/api/biblio-learning-finance.js.map +1 -0
  55. package/dist/api/biblio-learning-integrations.d.ts +60 -0
  56. package/dist/api/biblio-learning-integrations.js +215 -0
  57. package/dist/api/biblio-learning-integrations.js.map +1 -0
  58. package/dist/api/biblio-learning-membership.d.ts +24 -0
  59. package/dist/api/biblio-learning-membership.js +69 -0
  60. package/dist/api/biblio-learning-membership.js.map +1 -0
  61. package/dist/api/biblio-learning.d.ts +222 -0
  62. package/dist/api/biblio-learning.js +697 -0
  63. package/dist/api/biblio-learning.js.map +1 -0
  64. package/dist/api/biblio-library.d.ts +1 -1
  65. package/dist/api/biblio-library.js.map +1 -1
  66. package/dist/api/biblio-nextory.d.ts +1 -1
  67. package/dist/api/biblio-nextory.js.map +1 -1
  68. package/dist/api/biblio-press.d.ts +1 -1
  69. package/dist/api/biblio-press.js.map +1 -1
  70. package/dist/api/biblio-search.d.ts +1 -1
  71. package/dist/api/biblio-search.js.map +1 -1
  72. package/dist/api/biblio-telemetry.d.ts +1 -1
  73. package/dist/api/biblio-telemetry.js.map +1 -1
  74. package/dist/api/consumption.d.ts +1 -1
  75. package/dist/api/consumption.js.map +1 -1
  76. package/dist/api/cvs-app.d.ts +1 -1
  77. package/dist/api/cvs-app.js.map +1 -1
  78. package/dist/api/cvs-documents.d.ts +1 -1
  79. package/dist/api/cvs-documents.js.map +1 -1
  80. package/dist/api/cvs-favorites.d.ts +1 -1
  81. package/dist/api/cvs-favorites.js.map +1 -1
  82. package/dist/api/cvs-ils.d.ts +1 -1
  83. package/dist/api/cvs-ils.js.map +1 -1
  84. package/dist/api/cvs-loans.d.ts +1 -1
  85. package/dist/api/cvs-loans.js.map +1 -1
  86. package/dist/api/cvs-payments.d.ts +1 -1
  87. package/dist/api/cvs-payments.js.map +1 -1
  88. package/dist/api/cvs-streaming.d.ts +1 -1
  89. package/dist/api/cvs-streaming.js.map +1 -1
  90. package/dist/api/index.d.ts +11 -1
  91. package/dist/api/index.js +11 -1
  92. package/dist/api/partner-catalogue.d.ts +1 -1
  93. package/dist/api/partner-catalogue.js.map +1 -1
  94. package/dist/api/partner-reader.d.ts +1 -1
  95. package/dist/api/partner-reader.js.map +1 -1
  96. package/dist/api/profiles.d.ts +1 -1
  97. package/dist/api/profiles.js.map +1 -1
  98. package/dist/api/search.d.ts +1 -1
  99. package/dist/api/search.js.map +1 -1
  100. package/dist/api/tutoring-catalogue.d.ts +1 -1
  101. package/dist/api/tutoring-catalogue.js.map +1 -1
  102. package/dist/api/tutoring-chat.d.ts +1 -1
  103. package/dist/api/tutoring-chat.js.map +1 -1
  104. package/dist/api/tutoring-dispatch.d.ts +1 -1
  105. package/dist/api/tutoring-dispatch.js.map +1 -1
  106. package/dist/api/tutoring-practitioner.d.ts +1 -1
  107. package/dist/api/tutoring-practitioner.js.map +1 -1
  108. package/dist/api/tutoring-requests.d.ts +1 -1
  109. package/dist/api/tutoring-requests.js.map +1 -1
  110. package/dist/chunks/client2.d.ts +1 -1
  111. package/dist/chunks/connection.d.ts +1 -1
  112. package/dist/chunks/index.d.ts +10062 -3487
  113. package/dist/index.d.ts +3 -3
  114. package/dist/index.js +3 -3
  115. package/dist/index.js.map +1 -1
  116. package/dist/models.d.ts +2 -2
  117. package/dist/models.js +329 -1
  118. package/dist/models.js.map +1 -1
  119. package/dist/react/account.d.ts +1 -1
  120. package/dist/react/account.js +1 -1
  121. package/dist/react/account.js.map +1 -1
  122. package/dist/react/admin-catalogue.d.ts +1 -1
  123. package/dist/react/admin-catalogue.js +1 -1
  124. package/dist/react/admin-catalogue.js.map +1 -1
  125. package/dist/react/admin-consumption.d.ts +1 -1
  126. package/dist/react/admin-consumption.js +1 -1
  127. package/dist/react/admin-consumption.js.map +1 -1
  128. package/dist/react/admin-contracts.d.ts +1 -1
  129. package/dist/react/admin-contracts.js +1 -1
  130. package/dist/react/admin-contracts.js.map +1 -1
  131. package/dist/react/admin-desk.d.ts +1 -1
  132. package/dist/react/admin-desk.js +1 -1
  133. package/dist/react/admin-desk.js.map +1 -1
  134. package/dist/react/admin-licenses.d.ts +1 -1
  135. package/dist/react/admin-licenses.js +1 -1
  136. package/dist/react/admin-licenses.js.map +1 -1
  137. package/dist/react/admin-partner-selections.d.ts +1 -1
  138. package/dist/react/admin-partner-selections.js +1 -1
  139. package/dist/react/admin-partner-selections.js.map +1 -1
  140. package/dist/react/admin-patrons.d.ts +1 -1
  141. package/dist/react/admin-patrons.js +1 -1
  142. package/dist/react/admin-patrons.js.map +1 -1
  143. package/dist/react/admin-reviews.d.ts +1 -1
  144. package/dist/react/admin-reviews.js +1 -1
  145. package/dist/react/admin-reviews.js.map +1 -1
  146. package/dist/react/admin-roles.d.ts +1 -1
  147. package/dist/react/admin-roles.js +1 -1
  148. package/dist/react/admin-roles.js.map +1 -1
  149. package/dist/react/admin-support.d.ts +1 -1
  150. package/dist/react/admin-support.js +1 -1
  151. package/dist/react/admin-support.js.map +1 -1
  152. package/dist/react/admin-tenants.d.ts +1 -1
  153. package/dist/react/admin-tenants.js +1 -1
  154. package/dist/react/admin-tenants.js.map +1 -1
  155. package/dist/react/admin-tutoring.d.ts +1 -1
  156. package/dist/react/admin-tutoring.js +1 -1
  157. package/dist/react/admin-tutoring.js.map +1 -1
  158. package/dist/react/auth.d.ts +1 -1
  159. package/dist/react/auth.js +1 -1
  160. package/dist/react/auth.js.map +1 -1
  161. package/dist/react/biblio-billing-webhooks.d.ts +56 -0
  162. package/dist/react/biblio-billing-webhooks.js +126 -0
  163. package/dist/react/biblio-billing-webhooks.js.map +1 -0
  164. package/dist/react/biblio-billing.d.ts +876 -0
  165. package/dist/react/biblio-billing.js +1491 -0
  166. package/dist/react/biblio-billing.js.map +1 -0
  167. package/dist/react/biblio-catalogue.d.ts +1 -1
  168. package/dist/react/biblio-catalogue.js +1 -1
  169. package/dist/react/biblio-catalogue.js.map +1 -1
  170. package/dist/react/biblio-home.d.ts +1 -1
  171. package/dist/react/biblio-home.js +1 -1
  172. package/dist/react/biblio-home.js.map +1 -1
  173. package/dist/react/biblio-learning-author-profiles.d.ts +513 -0
  174. package/dist/react/biblio-learning-author-profiles.js +795 -0
  175. package/dist/react/biblio-learning-author-profiles.js.map +1 -0
  176. package/dist/react/biblio-learning-authoring.d.ts +745 -0
  177. package/dist/react/biblio-learning-authoring.js +1335 -0
  178. package/dist/react/biblio-learning-authoring.js.map +1 -0
  179. package/dist/react/biblio-learning-editorial.d.ts +264 -0
  180. package/dist/react/biblio-learning-editorial.js +371 -0
  181. package/dist/react/biblio-learning-editorial.js.map +1 -0
  182. package/dist/react/biblio-learning-feedback.d.ts +280 -0
  183. package/dist/react/biblio-learning-feedback.js +433 -0
  184. package/dist/react/biblio-learning-feedback.js.map +1 -0
  185. package/dist/react/biblio-learning-finance.d.ts +868 -0
  186. package/dist/react/biblio-learning-finance.js +1439 -0
  187. package/dist/react/biblio-learning-finance.js.map +1 -0
  188. package/dist/react/biblio-learning-integrations.d.ts +237 -0
  189. package/dist/react/biblio-learning-integrations.js +483 -0
  190. package/dist/react/biblio-learning-integrations.js.map +1 -0
  191. package/dist/react/biblio-learning-membership.d.ts +99 -0
  192. package/dist/react/biblio-learning-membership.js +165 -0
  193. package/dist/react/biblio-learning-membership.js.map +1 -0
  194. package/dist/react/biblio-learning.d.ts +1047 -0
  195. package/dist/react/biblio-learning.js +1667 -0
  196. package/dist/react/biblio-learning.js.map +1 -0
  197. package/dist/react/biblio-library.d.ts +1 -1
  198. package/dist/react/biblio-library.js +1 -1
  199. package/dist/react/biblio-library.js.map +1 -1
  200. package/dist/react/biblio-nextory.d.ts +1 -1
  201. package/dist/react/biblio-nextory.js +1 -1
  202. package/dist/react/biblio-nextory.js.map +1 -1
  203. package/dist/react/biblio-press.d.ts +1 -1
  204. package/dist/react/biblio-press.js +1 -1
  205. package/dist/react/biblio-press.js.map +1 -1
  206. package/dist/react/biblio-search.d.ts +1 -1
  207. package/dist/react/biblio-search.js +1 -1
  208. package/dist/react/biblio-search.js.map +1 -1
  209. package/dist/react/biblio-telemetry.d.ts +1 -1
  210. package/dist/react/biblio-telemetry.js +1 -1
  211. package/dist/react/biblio-telemetry.js.map +1 -1
  212. package/dist/react/chat.d.ts +1 -1
  213. package/dist/react/consumption.d.ts +1 -1
  214. package/dist/react/consumption.js +1 -1
  215. package/dist/react/consumption.js.map +1 -1
  216. package/dist/react/cvs-app.d.ts +1 -1
  217. package/dist/react/cvs-app.js +1 -1
  218. package/dist/react/cvs-app.js.map +1 -1
  219. package/dist/react/cvs-documents.d.ts +1 -1
  220. package/dist/react/cvs-documents.js +1 -1
  221. package/dist/react/cvs-documents.js.map +1 -1
  222. package/dist/react/cvs-favorites.d.ts +1 -1
  223. package/dist/react/cvs-favorites.js +1 -1
  224. package/dist/react/cvs-favorites.js.map +1 -1
  225. package/dist/react/cvs-ils.d.ts +1 -1
  226. package/dist/react/cvs-ils.js +1 -1
  227. package/dist/react/cvs-ils.js.map +1 -1
  228. package/dist/react/cvs-loans.d.ts +1 -1
  229. package/dist/react/cvs-loans.js +1 -1
  230. package/dist/react/cvs-loans.js.map +1 -1
  231. package/dist/react/cvs-payments.d.ts +1 -1
  232. package/dist/react/cvs-payments.js +1 -1
  233. package/dist/react/cvs-payments.js.map +1 -1
  234. package/dist/react/cvs-streaming.d.ts +1 -1
  235. package/dist/react/cvs-streaming.js +1 -1
  236. package/dist/react/cvs-streaming.js.map +1 -1
  237. package/dist/react/index.d.ts +11 -1
  238. package/dist/react/index.js +11 -1
  239. package/dist/react/partner-catalogue.d.ts +1 -1
  240. package/dist/react/partner-catalogue.js +1 -1
  241. package/dist/react/partner-catalogue.js.map +1 -1
  242. package/dist/react/partner-reader.d.ts +1 -1
  243. package/dist/react/partner-reader.js +1 -1
  244. package/dist/react/partner-reader.js.map +1 -1
  245. package/dist/react/profiles.d.ts +1 -1
  246. package/dist/react/profiles.js +1 -1
  247. package/dist/react/profiles.js.map +1 -1
  248. package/dist/react/search.d.ts +1 -1
  249. package/dist/react/search.js +1 -1
  250. package/dist/react/search.js.map +1 -1
  251. package/dist/react/tutoring-catalogue.d.ts +1 -1
  252. package/dist/react/tutoring-catalogue.js +1 -1
  253. package/dist/react/tutoring-catalogue.js.map +1 -1
  254. package/dist/react/tutoring-chat.d.ts +1 -1
  255. package/dist/react/tutoring-chat.js +1 -1
  256. package/dist/react/tutoring-chat.js.map +1 -1
  257. package/dist/react/tutoring-dispatch.d.ts +1 -1
  258. package/dist/react/tutoring-dispatch.js +1 -1
  259. package/dist/react/tutoring-dispatch.js.map +1 -1
  260. package/dist/react/tutoring-practitioner.d.ts +1 -1
  261. package/dist/react/tutoring-practitioner.js +1 -1
  262. package/dist/react/tutoring-practitioner.js.map +1 -1
  263. package/dist/react/tutoring-requests.d.ts +1 -1
  264. package/dist/react/tutoring-requests.js +1 -1
  265. package/dist/react/tutoring-requests.js.map +1 -1
  266. package/package.json +7 -7
@@ -0,0 +1,1667 @@
1
+ "use client";
2
+ import { r as request } from "../chunks/client.js";
3
+ import { useMutation, useQuery } from "@tanstack/react-query";
4
+ //#region src/react/biblio-learning/biblio-learning.ts
5
+ /**
6
+ * Generated by orval 🍺
7
+ * Do not edit manually.
8
+ * Mozaik backend
9
+ * Four products behind one API — Biblio, Médiathèques, the partner catalogues (Nextory and YouScribe) and Prof Express. Authentication is Keycloak SSO only, once, for all of them: see the **auth** section below for the browser flow and the three failure modes.
10
+ * OpenAPI spec version: 0.13.0
11
+ */
12
+ const withQueryKey = (query, queryKey) => {
13
+ const result = { queryKey };
14
+ for (const key of Object.keys(query)) {
15
+ if (key === "queryKey") continue;
16
+ Object.defineProperty(result, key, {
17
+ enumerable: true,
18
+ configurable: true,
19
+ get: () => query[key]
20
+ });
21
+ }
22
+ return result;
23
+ };
24
+ const getLearningStartAttemptUrl = (assessmentId) => {
25
+ return `/learning/assessments/${assessmentId}/attempts`;
26
+ };
27
+ /**
28
+ * Creates an immutable snapshot of the selected questions, ordering and pages. Course attempts need the profile's open reading session; provide lessonId when the assessment appears in multiple lessons. A lessonId without sessionId requests an allowed free preview. Path assessments use neither course session nor lesson. requestKey is scoped to profile and assessment: identical context replays the existing attempt; changed lesson/session context returns 409. Deadlines and attempt limits are enforced by the server. Preview results do not update course progress or score summaries.
29
+ * @summary Start or replay a scoped assessment attempt
30
+ */
31
+ const learningStartAttempt = async (assessmentId, learningAttemptStartWrite, options) => {
32
+ const getHeaders = (h) => {
33
+ if (!h) return {};
34
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
35
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
36
+ const headers = {};
37
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
38
+ return headers;
39
+ };
40
+ return request(getLearningStartAttemptUrl(assessmentId), {
41
+ ...options,
42
+ method: "POST",
43
+ headers: {
44
+ "Content-Type": "application/json",
45
+ ...getHeaders(options?.headers)
46
+ },
47
+ body: JSON.stringify(learningAttemptStartWrite)
48
+ });
49
+ };
50
+ const getLearningStartAttemptMutationKey = () => ["learningStartAttempt"];
51
+ const getLearningStartAttemptMutationOptions = (options) => {
52
+ const mutationKey = getLearningStartAttemptMutationKey();
53
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
54
+ ...options,
55
+ mutation: {
56
+ ...options.mutation,
57
+ mutationKey
58
+ }
59
+ } : {
60
+ mutation: { mutationKey },
61
+ request: void 0
62
+ };
63
+ const mutationFn = (props) => {
64
+ const { assessmentId, data } = props ?? {};
65
+ return learningStartAttempt(assessmentId, data, requestOptions);
66
+ };
67
+ return {
68
+ mutationFn,
69
+ ...mutationOptions
70
+ };
71
+ };
72
+ /**
73
+ * @summary Start or replay a scoped assessment attempt
74
+ */
75
+ const useLearningStartAttempt = (options, queryClient) => {
76
+ return useMutation(getLearningStartAttemptMutationOptions(options), queryClient);
77
+ };
78
+ const getLearningReadAttemptUrl = (attemptId) => {
79
+ return `/learning/attempts/${attemptId}`;
80
+ };
81
+ /**
82
+ * Returns only an attempt owned by the effective profile. In-progress native attempts recheck their learning context; completed and historical evidence remains readable by its owner. Public questions never include answer keys. Corrections and answer grades appear after completion/expiry, or for answered questions when immediate feedback is configured. Historical attempts return retained answers and scores without inventing a replayable question definition. This read does not itself finalize an elapsed deadline.
83
+ * @summary Read the profile's attempt and available feedback
84
+ */
85
+ const learningReadAttempt = async (attemptId, options) => {
86
+ return request(getLearningReadAttemptUrl(attemptId), {
87
+ ...options,
88
+ method: "GET"
89
+ });
90
+ };
91
+ const getLearningReadAttemptQueryKey = (attemptId) => {
92
+ return [`/learning/attempts/${attemptId}`];
93
+ };
94
+ const getLearningReadAttemptQueryOptions = (attemptId, options) => {
95
+ const { query: queryOptions, request: requestOptions } = options ?? {};
96
+ const queryKey = queryOptions?.queryKey ?? getLearningReadAttemptQueryKey(attemptId);
97
+ const queryFn = ({ signal }) => learningReadAttempt(attemptId, {
98
+ signal,
99
+ ...requestOptions
100
+ });
101
+ return {
102
+ queryKey,
103
+ queryFn,
104
+ enabled: attemptId !== null && attemptId !== void 0,
105
+ ...queryOptions
106
+ };
107
+ };
108
+ /**
109
+ * @summary Read the profile's attempt and available feedback
110
+ */
111
+ function useLearningReadAttempt(attemptId, options, queryClient) {
112
+ const queryOptions = getLearningReadAttemptQueryOptions(attemptId, options);
113
+ const query = useQuery(queryOptions, queryClient);
114
+ return withQueryKey(query, queryOptions.queryKey);
115
+ }
116
+ const getLearningAbandonAttemptUrl = (attemptId) => {
117
+ return `/learning/attempts/${attemptId}/abandon`;
118
+ };
119
+ /**
120
+ * Changes the effective profile's in-progress native attempt to abandoned and records finishedAt. Saved responses remain in history; abandoning does not calculate a score or grant completion. Repeating an abandoned or other terminal native attempt returns its existing state. Imported attempts are historical evidence and cannot be abandoned.
121
+ * @summary Abandon an unfinished native attempt
122
+ */
123
+ const learningAbandonAttempt = async (attemptId, options) => {
124
+ return request(getLearningAbandonAttemptUrl(attemptId), {
125
+ ...options,
126
+ method: "POST"
127
+ });
128
+ };
129
+ const getLearningAbandonAttemptMutationKey = () => ["learningAbandonAttempt"];
130
+ const getLearningAbandonAttemptMutationOptions = (options) => {
131
+ const mutationKey = getLearningAbandonAttemptMutationKey();
132
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
133
+ ...options,
134
+ mutation: {
135
+ ...options.mutation,
136
+ mutationKey
137
+ }
138
+ } : {
139
+ mutation: { mutationKey },
140
+ request: void 0
141
+ };
142
+ const mutationFn = (props) => {
143
+ const { attemptId } = props ?? {};
144
+ return learningAbandonAttempt(attemptId, requestOptions);
145
+ };
146
+ return {
147
+ mutationFn,
148
+ ...mutationOptions
149
+ };
150
+ };
151
+ /**
152
+ * @summary Abandon an unfinished native attempt
153
+ */
154
+ const useLearningAbandonAttempt = (options, queryClient) => {
155
+ return useMutation(getLearningAbandonAttemptMutationOptions(options), queryClient);
156
+ };
157
+ const getLearningAnswerQuestionUrl = (attemptId, questionKey) => {
158
+ return `/learning/attempts/${attemptId}/answers/${questionKey}`;
159
+ };
160
+ /**
161
+ * Use the selected question's key and kind-specific response object. Before finalization answers can be replaced unless immediate feedback has made the first response final. An identical saved response can be replayed after finalization; a different final answer returns 409. An elapsed deadline finalizes the attempt as expired and rejects the late answer. Uploaded reflection answers must reference this profile's completed upload reserved for this exact attempt and question. The response returns the entire attempt with only currently authorized feedback.
162
+ * @summary Save a question response in the owned attempt
163
+ */
164
+ const learningAnswerQuestion = async (attemptId, questionKey, learningAnswerWrite, options) => {
165
+ const getHeaders = (h) => {
166
+ if (!h) return {};
167
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
168
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
169
+ const headers = {};
170
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
171
+ return headers;
172
+ };
173
+ return request(getLearningAnswerQuestionUrl(attemptId, questionKey), {
174
+ ...options,
175
+ method: "PUT",
176
+ headers: {
177
+ "Content-Type": "application/json",
178
+ ...getHeaders(options?.headers)
179
+ },
180
+ body: JSON.stringify(learningAnswerWrite)
181
+ });
182
+ };
183
+ const getLearningAnswerQuestionMutationKey = () => ["learningAnswerQuestion"];
184
+ const getLearningAnswerQuestionMutationOptions = (options) => {
185
+ const mutationKey = getLearningAnswerQuestionMutationKey();
186
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
187
+ ...options,
188
+ mutation: {
189
+ ...options.mutation,
190
+ mutationKey
191
+ }
192
+ } : {
193
+ mutation: { mutationKey },
194
+ request: void 0
195
+ };
196
+ const mutationFn = (props) => {
197
+ const { attemptId, questionKey, data } = props ?? {};
198
+ return learningAnswerQuestion(attemptId, questionKey, data, requestOptions);
199
+ };
200
+ return {
201
+ mutationFn,
202
+ ...mutationOptions
203
+ };
204
+ };
205
+ /**
206
+ * @summary Save a question response in the owned attempt
207
+ */
208
+ const useLearningAnswerQuestion = (options, queryClient) => {
209
+ return useMutation(getLearningAnswerQuestionMutationOptions(options), queryClient);
210
+ };
211
+ const getLearningFinishAttemptUrl = (attemptId) => {
212
+ return `/learning/attempts/${attemptId}/finish`;
213
+ };
214
+ /**
215
+ * Requires the owned attempt's learning context. Before its deadline every selected question must have a response, including reflection and information acknowledgements. After the deadline the attempt is finalized as expired, with unanswered scored questions counted as zero. Returns corrections and a percentage score, or null for an unscored assessment. Eligible native results update score summaries and completion evidence; preview results do not. Repeating a terminal attempt returns its existing state.
216
+ * @summary Finalize answers and compute assessment results
217
+ */
218
+ const learningFinishAttempt = async (attemptId, options) => {
219
+ return request(getLearningFinishAttemptUrl(attemptId), {
220
+ ...options,
221
+ method: "POST"
222
+ });
223
+ };
224
+ const getLearningFinishAttemptMutationKey = () => ["learningFinishAttempt"];
225
+ const getLearningFinishAttemptMutationOptions = (options) => {
226
+ const mutationKey = getLearningFinishAttemptMutationKey();
227
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
228
+ ...options,
229
+ mutation: {
230
+ ...options.mutation,
231
+ mutationKey
232
+ }
233
+ } : {
234
+ mutation: { mutationKey },
235
+ request: void 0
236
+ };
237
+ const mutationFn = (props) => {
238
+ const { attemptId } = props ?? {};
239
+ return learningFinishAttempt(attemptId, requestOptions);
240
+ };
241
+ return {
242
+ mutationFn,
243
+ ...mutationOptions
244
+ };
245
+ };
246
+ /**
247
+ * @summary Finalize answers and compute assessment results
248
+ */
249
+ const useLearningFinishAttempt = (options, queryClient) => {
250
+ return useMutation(getLearningFinishAttemptMutationOptions(options), queryClient);
251
+ };
252
+ const getLearningRateExercisePageUrl = (attemptId, pageKey) => {
253
+ return `/learning/attempts/${attemptId}/pages/${pageKey}/self-rating`;
254
+ };
255
+ /**
256
+ * Requires an owned native exercise attempt containing pageKey and full learning access. Saves a rating from 1 to 5 for this profile and exercise page; later submissions replace the rating and mark the page's self-reflection complete. Preview attempts cannot save ratings. This does not submit answers, award points or substitute for assessment completion.
257
+ * @summary Save a private exercise-page self-rating
258
+ */
259
+ const learningRateExercisePage = async (attemptId, pageKey, learningSelfRatingWrite, options) => {
260
+ const getHeaders = (h) => {
261
+ if (!h) return {};
262
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
263
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
264
+ const headers = {};
265
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
266
+ return headers;
267
+ };
268
+ return request(getLearningRateExercisePageUrl(attemptId, pageKey), {
269
+ ...options,
270
+ method: "PUT",
271
+ headers: {
272
+ "Content-Type": "application/json",
273
+ ...getHeaders(options?.headers)
274
+ },
275
+ body: JSON.stringify(learningSelfRatingWrite)
276
+ });
277
+ };
278
+ const getLearningRateExercisePageMutationKey = () => ["learningRateExercisePage"];
279
+ const getLearningRateExercisePageMutationOptions = (options) => {
280
+ const mutationKey = getLearningRateExercisePageMutationKey();
281
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
282
+ ...options,
283
+ mutation: {
284
+ ...options.mutation,
285
+ mutationKey
286
+ }
287
+ } : {
288
+ mutation: { mutationKey },
289
+ request: void 0
290
+ };
291
+ const mutationFn = (props) => {
292
+ const { attemptId, pageKey, data } = props ?? {};
293
+ return learningRateExercisePage(attemptId, pageKey, data, requestOptions);
294
+ };
295
+ return {
296
+ mutationFn,
297
+ ...mutationOptions
298
+ };
299
+ };
300
+ /**
301
+ * @summary Save a private exercise-page self-rating
302
+ */
303
+ const useLearningRateExercisePage = (options, queryClient) => {
304
+ return useMutation(getLearningRateExercisePageMutationOptions(options), queryClient);
305
+ };
306
+ const getLearningReserveExerciseUploadUrl = (attemptId, questionKey) => {
307
+ return `/learning/attempts/${attemptId}/questions/${questionKey}/uploads`;
308
+ };
309
+ /**
310
+ * Requires the effective profile's in-progress, unexpired native attempt and a reflection question configured for upload or text_or_upload. The MIME type must map to one of that question's allowedUploadKinds; exercise files are limited to 50 MiB (WebVTT remains limited to 2 MiB). Reserve, PUT the exact bytes to uploadUrl, then submit response.assetId using the answer operation. The uploaded asset remains scoped to this profile, attempt and question; reservation alone does not answer it.
311
+ * @summary Reserve a private uploaded reflection answer
312
+ */
313
+ const learningReserveExerciseUpload = async (attemptId, questionKey, learningUploadWrite, options) => {
314
+ const getHeaders = (h) => {
315
+ if (!h) return {};
316
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
317
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
318
+ const headers = {};
319
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
320
+ return headers;
321
+ };
322
+ return request(getLearningReserveExerciseUploadUrl(attemptId, questionKey), {
323
+ ...options,
324
+ method: "POST",
325
+ headers: {
326
+ "Content-Type": "application/json",
327
+ ...getHeaders(options?.headers)
328
+ },
329
+ body: JSON.stringify(learningUploadWrite)
330
+ });
331
+ };
332
+ const getLearningReserveExerciseUploadMutationKey = () => ["learningReserveExerciseUpload"];
333
+ const getLearningReserveExerciseUploadMutationOptions = (options) => {
334
+ const mutationKey = getLearningReserveExerciseUploadMutationKey();
335
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
336
+ ...options,
337
+ mutation: {
338
+ ...options.mutation,
339
+ mutationKey
340
+ }
341
+ } : {
342
+ mutation: { mutationKey },
343
+ request: void 0
344
+ };
345
+ const mutationFn = (props) => {
346
+ const { attemptId, questionKey, data } = props ?? {};
347
+ return learningReserveExerciseUpload(attemptId, questionKey, data, requestOptions);
348
+ };
349
+ return {
350
+ mutationFn,
351
+ ...mutationOptions
352
+ };
353
+ };
354
+ /**
355
+ * @summary Reserve a private uploaded reflection answer
356
+ */
357
+ const useLearningReserveExerciseUpload = (options, queryClient) => {
358
+ return useMutation(getLearningReserveExerciseUploadMutationOptions(options), queryClient);
359
+ };
360
+ const getLearningReadAttemptResourceUrl = (attemptId, assetId) => {
361
+ return `/learning/attempts/${attemptId}/resources/${assetId}`;
362
+ };
363
+ /**
364
+ * Checks the profile's ownership and retained assessment context. Permits selected question/page media, allowed choice media and public hints. Correction resources become available after completion/expiry or after the corresponding answer when immediate feedback is configured. A submitted reflection upload is accessible only through its owning attempt and question. Resource IDs outside this authorized set return 404; returned delivery URLs may expire.
365
+ * @summary Resolve a resource authorized by the owned attempt
366
+ */
367
+ const learningReadAttemptResource = async (attemptId, assetId, options) => {
368
+ return request(getLearningReadAttemptResourceUrl(attemptId, assetId), {
369
+ ...options,
370
+ method: "GET"
371
+ });
372
+ };
373
+ const getLearningReadAttemptResourceQueryKey = (attemptId, assetId) => {
374
+ return [`/learning/attempts/${attemptId}/resources/${assetId}`];
375
+ };
376
+ const getLearningReadAttemptResourceQueryOptions = (attemptId, assetId, options) => {
377
+ const { query: queryOptions, request: requestOptions } = options ?? {};
378
+ const queryKey = queryOptions?.queryKey ?? getLearningReadAttemptResourceQueryKey(attemptId, assetId);
379
+ const queryFn = ({ signal }) => learningReadAttemptResource(attemptId, assetId, {
380
+ signal,
381
+ ...requestOptions
382
+ });
383
+ return {
384
+ queryKey,
385
+ queryFn,
386
+ enabled: attemptId !== null && attemptId !== void 0 && assetId !== null && assetId !== void 0,
387
+ ...queryOptions
388
+ };
389
+ };
390
+ /**
391
+ * @summary Resolve a resource authorized by the owned attempt
392
+ */
393
+ function useLearningReadAttemptResource(attemptId, assetId, options, queryClient) {
394
+ const queryOptions = getLearningReadAttemptResourceQueryOptions(attemptId, assetId, options);
395
+ const query = useQuery(queryOptions, queryClient);
396
+ return withQueryKey(query, queryOptions.queryKey);
397
+ }
398
+ const getLearningReserveCourseUploadUrl = (courseId) => {
399
+ return `/learning/author/courses/${courseId}/uploads`;
400
+ };
401
+ /**
402
+ * Requires edit authority on courseId. Reserves one immutable file with an exact byte count and declared MIME type for 15 minutes. Course files are limited to 200 MiB; WebVTT captions to 2 MiB. At most ten unexpired pending uploads may exist per profile. Send the raw bytes with authenticated PUT to uploadUrl, then use its returned assetId in the course definition. Each reservation request creates a new reservation.
403
+ * @summary Reserve a file upload for course authoring
404
+ */
405
+ const learningReserveCourseUpload = async (courseId, learningUploadWrite, options) => {
406
+ const getHeaders = (h) => {
407
+ if (!h) return {};
408
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
409
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
410
+ const headers = {};
411
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
412
+ return headers;
413
+ };
414
+ return request(getLearningReserveCourseUploadUrl(courseId), {
415
+ ...options,
416
+ method: "POST",
417
+ headers: {
418
+ "Content-Type": "application/json",
419
+ ...getHeaders(options?.headers)
420
+ },
421
+ body: JSON.stringify(learningUploadWrite)
422
+ });
423
+ };
424
+ const getLearningReserveCourseUploadMutationKey = () => ["learningReserveCourseUpload"];
425
+ const getLearningReserveCourseUploadMutationOptions = (options) => {
426
+ const mutationKey = getLearningReserveCourseUploadMutationKey();
427
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
428
+ ...options,
429
+ mutation: {
430
+ ...options.mutation,
431
+ mutationKey
432
+ }
433
+ } : {
434
+ mutation: { mutationKey },
435
+ request: void 0
436
+ };
437
+ const mutationFn = (props) => {
438
+ const { courseId, data } = props ?? {};
439
+ return learningReserveCourseUpload(courseId, data, requestOptions);
440
+ };
441
+ return {
442
+ mutationFn,
443
+ ...mutationOptions
444
+ };
445
+ };
446
+ /**
447
+ * @summary Reserve a file upload for course authoring
448
+ */
449
+ const useLearningReserveCourseUpload = (options, queryClient) => {
450
+ return useMutation(getLearningReserveCourseUploadMutationOptions(options), queryClient);
451
+ };
452
+ const getLearningReadCertificateUrl = (certificateId) => {
453
+ return `/learning/certificates/${certificateId}`;
454
+ };
455
+ /**
456
+ * Returns the immutable recipient, course title, edition and issuance date recorded for this profile's certificate. Another profile's certificate is not visible. This read does not require opening a new course session; documentUrl identifies the separately authenticated PDF download.
457
+ * @summary Read an issued certificate owned by the profile
458
+ */
459
+ const learningReadCertificate = async (certificateId, options) => {
460
+ return request(getLearningReadCertificateUrl(certificateId), {
461
+ ...options,
462
+ method: "GET"
463
+ });
464
+ };
465
+ const getLearningReadCertificateQueryKey = (certificateId) => {
466
+ return [`/learning/certificates/${certificateId}`];
467
+ };
468
+ const getLearningReadCertificateQueryOptions = (certificateId, options) => {
469
+ const { query: queryOptions, request: requestOptions } = options ?? {};
470
+ const queryKey = queryOptions?.queryKey ?? getLearningReadCertificateQueryKey(certificateId);
471
+ const queryFn = ({ signal }) => learningReadCertificate(certificateId, {
472
+ signal,
473
+ ...requestOptions
474
+ });
475
+ return {
476
+ queryKey,
477
+ queryFn,
478
+ enabled: certificateId !== null && certificateId !== void 0,
479
+ ...queryOptions
480
+ };
481
+ };
482
+ /**
483
+ * @summary Read an issued certificate owned by the profile
484
+ */
485
+ function useLearningReadCertificate(certificateId, options, queryClient) {
486
+ const queryOptions = getLearningReadCertificateQueryOptions(certificateId, options);
487
+ const query = useQuery(queryOptions, queryClient);
488
+ return withQueryKey(query, queryOptions.queryKey);
489
+ }
490
+ const getLearningDownloadCertificateUrl = (certificateId) => {
491
+ return `/learning/certificates/${certificateId}/document`;
492
+ };
493
+ /**
494
+ * Renders the certificate's retained recipient name, course title and issuance evidence as a PDF attachment. Only the effective profile that owns the certificate can download it. The successful response is application/pdf bytes with Content-Disposition attachment and private, no-store caching; it has no JSON body.
495
+ * @summary Download an owned completion certificate as PDF
496
+ */
497
+ const learningDownloadCertificate = async (certificateId, options) => {
498
+ return request(getLearningDownloadCertificateUrl(certificateId), {
499
+ ...options,
500
+ method: "GET"
501
+ });
502
+ };
503
+ const getLearningDownloadCertificateQueryKey = (certificateId) => {
504
+ return [`/learning/certificates/${certificateId}/document`];
505
+ };
506
+ const getLearningDownloadCertificateQueryOptions = (certificateId, options) => {
507
+ const { query: queryOptions, request: requestOptions } = options ?? {};
508
+ const queryKey = queryOptions?.queryKey ?? getLearningDownloadCertificateQueryKey(certificateId);
509
+ const queryFn = ({ signal }) => learningDownloadCertificate(certificateId, {
510
+ signal,
511
+ ...requestOptions
512
+ });
513
+ return {
514
+ queryKey,
515
+ queryFn,
516
+ enabled: certificateId !== null && certificateId !== void 0,
517
+ ...queryOptions
518
+ };
519
+ };
520
+ /**
521
+ * @summary Download an owned completion certificate as PDF
522
+ */
523
+ function useLearningDownloadCertificate(certificateId, options, queryClient) {
524
+ const queryOptions = getLearningDownloadCertificateQueryOptions(certificateId, options);
525
+ const query = useQuery(queryOptions, queryClient);
526
+ return withQueryKey(query, queryOptions.queryKey);
527
+ }
528
+ const getLearningReadCourseUrl = (courseId) => {
529
+ return `/learning/courses/${courseId}`;
530
+ };
531
+ /**
532
+ * Returns the effective profile's enrolled edition, or the latest published edition before enrollment. Eligibility uses the shared profile, age, category and entitlement rules; an allowed preview may expose the outline with hasFullAccess=false. This GET creates no enrollment or reading session. Check upgradeAvailable and latestRevisionId before offering an explicit edition upgrade. Lesson progress and final assessment IDs are included only with full access.
533
+ * @summary Read the selected course edition and progress
534
+ */
535
+ const learningReadCourse = async (courseId, options) => {
536
+ return request(getLearningReadCourseUrl(courseId), {
537
+ ...options,
538
+ method: "GET"
539
+ });
540
+ };
541
+ const getLearningReadCourseQueryKey = (courseId) => {
542
+ return [`/learning/courses/${courseId}`];
543
+ };
544
+ const getLearningReadCourseQueryOptions = (courseId, options) => {
545
+ const { query: queryOptions, request: requestOptions } = options ?? {};
546
+ const queryKey = queryOptions?.queryKey ?? getLearningReadCourseQueryKey(courseId);
547
+ const queryFn = ({ signal }) => learningReadCourse(courseId, {
548
+ signal,
549
+ ...requestOptions
550
+ });
551
+ return {
552
+ queryKey,
553
+ queryFn,
554
+ enabled: courseId !== null && courseId !== void 0,
555
+ ...queryOptions
556
+ };
557
+ };
558
+ /**
559
+ * @summary Read the selected course edition and progress
560
+ */
561
+ function useLearningReadCourse(courseId, options, queryClient) {
562
+ const queryOptions = getLearningReadCourseQueryOptions(courseId, options);
563
+ const query = useQuery(queryOptions, queryClient);
564
+ return withQueryKey(query, queryOptions.queryKey);
565
+ }
566
+ const getLearningIssueCertificateUrl = (courseId) => {
567
+ return `/learning/courses/${courseId}/certificate`;
568
+ };
569
+ /**
570
+ * Requires an existing current enrollment in a course with certification enabled. Recomputes evidence: every required lesson must be complete and every required assessment passed. Creates one certificate per profile and edition, retaining recipient name and course title as issued; repeating issuance returns the existing certificate. Evidence can support issuance without a new reading session. Use documentUrl to download the PDF.
571
+ * @summary Issue the profile's course completion certificate
572
+ */
573
+ const learningIssueCertificate = async (courseId, options) => {
574
+ return request(getLearningIssueCertificateUrl(courseId), {
575
+ ...options,
576
+ method: "POST"
577
+ });
578
+ };
579
+ const getLearningIssueCertificateMutationKey = () => ["learningIssueCertificate"];
580
+ const getLearningIssueCertificateMutationOptions = (options) => {
581
+ const mutationKey = getLearningIssueCertificateMutationKey();
582
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
583
+ ...options,
584
+ mutation: {
585
+ ...options.mutation,
586
+ mutationKey
587
+ }
588
+ } : {
589
+ mutation: { mutationKey },
590
+ request: void 0
591
+ };
592
+ const mutationFn = (props) => {
593
+ const { courseId } = props ?? {};
594
+ return learningIssueCertificate(courseId, requestOptions);
595
+ };
596
+ return {
597
+ mutationFn,
598
+ ...mutationOptions
599
+ };
600
+ };
601
+ /**
602
+ * @summary Issue the profile's course completion certificate
603
+ */
604
+ const useLearningIssueCertificate = (options, queryClient) => {
605
+ return useMutation(getLearningIssueCertificateMutationOptions(options), queryClient);
606
+ };
607
+ const getLearningEnrollUrl = (courseId) => {
608
+ return `/learning/courses/${courseId}/enrollment`;
609
+ };
610
+ /**
611
+ * Requires full access for the effective profile. Creates a current enrollment pinned to the published edition if none exists; otherwise retains the selected edition and progress. archived controls the reader's personal archive preference. Repeating the same preference does not duplicate enrollment. Opening a reading session is a separate explicit step.
612
+ * @summary Enroll in the course or set its archive preference
613
+ */
614
+ const learningEnroll = async (courseId, courseEnrollmentWrite, options) => {
615
+ const getHeaders = (h) => {
616
+ if (!h) return {};
617
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
618
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
619
+ const headers = {};
620
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
621
+ return headers;
622
+ };
623
+ return request(getLearningEnrollUrl(courseId), {
624
+ ...options,
625
+ method: "PUT",
626
+ headers: {
627
+ "Content-Type": "application/json",
628
+ ...getHeaders(options?.headers)
629
+ },
630
+ body: JSON.stringify(courseEnrollmentWrite)
631
+ });
632
+ };
633
+ const getLearningEnrollMutationKey = () => ["learningEnroll"];
634
+ const getLearningEnrollMutationOptions = (options) => {
635
+ const mutationKey = getLearningEnrollMutationKey();
636
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
637
+ ...options,
638
+ mutation: {
639
+ ...options.mutation,
640
+ mutationKey
641
+ }
642
+ } : {
643
+ mutation: { mutationKey },
644
+ request: void 0
645
+ };
646
+ const mutationFn = (props) => {
647
+ const { courseId, data } = props ?? {};
648
+ return learningEnroll(courseId, data, requestOptions);
649
+ };
650
+ return {
651
+ mutationFn,
652
+ ...mutationOptions
653
+ };
654
+ };
655
+ /**
656
+ * @summary Enroll in the course or set its archive preference
657
+ */
658
+ const useLearningEnroll = (options, queryClient) => {
659
+ return useMutation(getLearningEnrollMutationOptions(options), queryClient);
660
+ };
661
+ const getLearningReadEnrollmentHistoryUrl = (courseId, params) => {
662
+ const normalizedParams = new URLSearchParams();
663
+ Object.entries(params || {}).forEach(([key, value]) => {
664
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
665
+ });
666
+ const stringifiedParams = normalizedParams.toString();
667
+ return stringifiedParams.length > 0 ? `/learning/courses/${courseId}/enrollments?${stringifiedParams}` : `/learning/courses/${courseId}/enrollments`;
668
+ };
669
+ /**
670
+ * Requires current full course access and returns this profile's enrollments only, newest enrollment ID first. isCurrent identifies the selected edition; archived is a personal list preference independent of edition selection. Earlier progress and completedAt are preserved after an upgrade.
671
+ * @summary List the profile's course enrollments by edition
672
+ */
673
+ const learningReadEnrollmentHistory = async (courseId, params, options) => {
674
+ return request(getLearningReadEnrollmentHistoryUrl(courseId, params), {
675
+ ...options,
676
+ method: "GET"
677
+ });
678
+ };
679
+ const getLearningReadEnrollmentHistoryQueryKey = (courseId, params) => {
680
+ return [`/learning/courses/${courseId}/enrollments`, ...params ? [params] : []];
681
+ };
682
+ const getLearningReadEnrollmentHistoryQueryOptions = (courseId, params, options) => {
683
+ const { query: queryOptions, request: requestOptions } = options ?? {};
684
+ const queryKey = queryOptions?.queryKey ?? getLearningReadEnrollmentHistoryQueryKey(courseId, params);
685
+ const queryFn = ({ signal }) => learningReadEnrollmentHistory(courseId, params, {
686
+ signal,
687
+ ...requestOptions
688
+ });
689
+ return {
690
+ queryKey,
691
+ queryFn,
692
+ enabled: courseId !== null && courseId !== void 0,
693
+ ...queryOptions
694
+ };
695
+ };
696
+ /**
697
+ * @summary List the profile's course enrollments by edition
698
+ */
699
+ function useLearningReadEnrollmentHistory(courseId, params, options, queryClient) {
700
+ const queryOptions = getLearningReadEnrollmentHistoryQueryOptions(courseId, params, options);
701
+ const query = useQuery(queryOptions, queryClient);
702
+ return withQueryKey(query, queryOptions.queryKey);
703
+ }
704
+ const getLearningStartSessionUrl = (courseId) => {
705
+ return `/learning/courses/${courseId}/sessions`;
706
+ };
707
+ /**
708
+ * Requires full course access, creates enrollment if needed and opens a shared consumption lease pinned to the selected edition. Generate requestKey once for the opening action and reuse it after uncertain network outcomes. The key is scoped to the effective profile: the same course returns its existing session, including a closed one; reuse for another course returns 409. Use a new key for a new reading session, then open a lesson with the returned sessionId.
709
+ * @summary Open an entitled course reading session
710
+ */
711
+ const learningStartSession = async (courseId, learningSessionStartWrite, options) => {
712
+ const getHeaders = (h) => {
713
+ if (!h) return {};
714
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
715
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
716
+ const headers = {};
717
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
718
+ return headers;
719
+ };
720
+ return request(getLearningStartSessionUrl(courseId), {
721
+ ...options,
722
+ method: "POST",
723
+ headers: {
724
+ "Content-Type": "application/json",
725
+ ...getHeaders(options?.headers)
726
+ },
727
+ body: JSON.stringify(learningSessionStartWrite)
728
+ });
729
+ };
730
+ const getLearningStartSessionMutationKey = () => ["learningStartSession"];
731
+ const getLearningStartSessionMutationOptions = (options) => {
732
+ const mutationKey = getLearningStartSessionMutationKey();
733
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
734
+ ...options,
735
+ mutation: {
736
+ ...options.mutation,
737
+ mutationKey
738
+ }
739
+ } : {
740
+ mutation: { mutationKey },
741
+ request: void 0
742
+ };
743
+ const mutationFn = (props) => {
744
+ const { courseId, data } = props ?? {};
745
+ return learningStartSession(courseId, data, requestOptions);
746
+ };
747
+ return {
748
+ mutationFn,
749
+ ...mutationOptions
750
+ };
751
+ };
752
+ /**
753
+ * @summary Open an entitled course reading session
754
+ */
755
+ const useLearningStartSession = (options, queryClient) => {
756
+ return useMutation(getLearningStartSessionMutationOptions(options), queryClient);
757
+ };
758
+ const getLearningUpgradeCourseEditionUrl = (courseId) => {
759
+ return `/learning/courses/${courseId}/upgrade-edition`;
760
+ };
761
+ /**
762
+ * Requires full course access and an existing current enrollment. Send its revisionId as expectedRevisionId and latestRevisionId as targetRevisionId. Closes open course reading sessions, retains earlier enrollment and completion evidence, and selects the target edition without copying old lesson progress. Repeating the same target succeeds; stale expectations or a target other than the latest publication return 409.
763
+ * @summary Move enrollment to the latest published edition
764
+ */
765
+ const learningUpgradeCourseEdition = async (courseId, courseEditionUpgradeWrite, options) => {
766
+ const getHeaders = (h) => {
767
+ if (!h) return {};
768
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
769
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
770
+ const headers = {};
771
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
772
+ return headers;
773
+ };
774
+ return request(getLearningUpgradeCourseEditionUrl(courseId), {
775
+ ...options,
776
+ method: "POST",
777
+ headers: {
778
+ "Content-Type": "application/json",
779
+ ...getHeaders(options?.headers)
780
+ },
781
+ body: JSON.stringify(courseEditionUpgradeWrite)
782
+ });
783
+ };
784
+ const getLearningUpgradeCourseEditionMutationKey = () => ["learningUpgradeCourseEdition"];
785
+ const getLearningUpgradeCourseEditionMutationOptions = (options) => {
786
+ const mutationKey = getLearningUpgradeCourseEditionMutationKey();
787
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
788
+ ...options,
789
+ mutation: {
790
+ ...options.mutation,
791
+ mutationKey
792
+ }
793
+ } : {
794
+ mutation: { mutationKey },
795
+ request: void 0
796
+ };
797
+ const mutationFn = (props) => {
798
+ const { courseId, data } = props ?? {};
799
+ return learningUpgradeCourseEdition(courseId, data, requestOptions);
800
+ };
801
+ return {
802
+ mutationFn,
803
+ ...mutationOptions
804
+ };
805
+ };
806
+ /**
807
+ * @summary Move enrollment to the latest published edition
808
+ */
809
+ const useLearningUpgradeCourseEdition = (options, queryClient) => {
810
+ return useMutation(getLearningUpgradeCourseEditionMutationOptions(options), queryClient);
811
+ };
812
+ const getLearningAnswerSelectionEvidenceUrl = (params) => {
813
+ const normalizedParams = new URLSearchParams();
814
+ Object.entries(params || {}).forEach(([key, value]) => {
815
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
816
+ });
817
+ const stringifiedParams = normalizedParams.toString();
818
+ return stringifiedParams.length > 0 ? `/learning/history/answer-selections?${stringifiedParams}` : `/learning/history/answer-selections`;
819
+ };
820
+ /**
821
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Source flags and counters are reported evidence, not newly computed grades. Missing dates, links and scoring remain null; a recorded completion flag does not establish a native pass result. attemptId selects an owned historical attempt; unlinkedOnly=true selects rows with no stored attempt link and cannot be combined with attemptId. Optional object filters apply within that same ownership scope. Results are ordered by history ID descending and paginated after filtering. questionId optionally filters by a local question mapping. choiceId, questionId, componentKey and attemptId may be incomplete. A null attemptId in the response does not create a synthetic attempt. Selection records reveal what was retained, without reconstructing correctness or scores.
822
+ * @summary List my historical answer selections
823
+ */
824
+ const learningAnswerSelectionEvidence = async (params, options) => {
825
+ return request(getLearningAnswerSelectionEvidenceUrl(params), {
826
+ ...options,
827
+ method: "GET"
828
+ });
829
+ };
830
+ const getLearningAnswerSelectionEvidenceQueryKey = (params) => {
831
+ return [`/learning/history/answer-selections`, ...params ? [params] : []];
832
+ };
833
+ const getLearningAnswerSelectionEvidenceQueryOptions = (params, options) => {
834
+ const { query: queryOptions, request: requestOptions } = options ?? {};
835
+ const queryKey = queryOptions?.queryKey ?? getLearningAnswerSelectionEvidenceQueryKey(params);
836
+ const queryFn = ({ signal }) => learningAnswerSelectionEvidence(params, {
837
+ signal,
838
+ ...requestOptions
839
+ });
840
+ return {
841
+ queryKey,
842
+ queryFn,
843
+ ...queryOptions
844
+ };
845
+ };
846
+ /**
847
+ * @summary List my historical answer selections
848
+ */
849
+ function useLearningAnswerSelectionEvidence(params, options, queryClient) {
850
+ const queryOptions = getLearningAnswerSelectionEvidenceQueryOptions(params, options);
851
+ const query = useQuery(queryOptions, queryClient);
852
+ return withQueryKey(query, queryOptions.queryKey);
853
+ }
854
+ const getLearningAnswerSelectionDetailUrl = (historyId) => {
855
+ return `/learning/history/answer-selections/${historyId}`;
856
+ };
857
+ /**
858
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Source flags and counters are reported evidence, not newly computed grades. Missing dates, links and scoring remain null; a recorded completion flag does not establish a native pass result. historyId identifies a retained selection record rather than a current answer or question. Optional local mappings remain null when unavailable; no grade or completion date is inferred. The source selection's recorded creation timestamp is returned as stored.
859
+ * @summary Read my historical answer selection
860
+ */
861
+ const learningAnswerSelectionDetail = async (historyId, options) => {
862
+ return request(getLearningAnswerSelectionDetailUrl(historyId), {
863
+ ...options,
864
+ method: "GET"
865
+ });
866
+ };
867
+ const getLearningAnswerSelectionDetailQueryKey = (historyId) => {
868
+ return [`/learning/history/answer-selections/${historyId}`];
869
+ };
870
+ const getLearningAnswerSelectionDetailQueryOptions = (historyId, options) => {
871
+ const { query: queryOptions, request: requestOptions } = options ?? {};
872
+ const queryKey = queryOptions?.queryKey ?? getLearningAnswerSelectionDetailQueryKey(historyId);
873
+ const queryFn = ({ signal }) => learningAnswerSelectionDetail(historyId, {
874
+ signal,
875
+ ...requestOptions
876
+ });
877
+ return {
878
+ queryKey,
879
+ queryFn,
880
+ enabled: historyId !== null && historyId !== void 0,
881
+ ...queryOptions
882
+ };
883
+ };
884
+ /**
885
+ * @summary Read my historical answer selection
886
+ */
887
+ function useLearningAnswerSelectionDetail(historyId, options, queryClient) {
888
+ const queryOptions = getLearningAnswerSelectionDetailQueryOptions(historyId, options);
889
+ const query = useQuery(queryOptions, queryClient);
890
+ return withQueryKey(query, queryOptions.queryKey);
891
+ }
892
+ const getLearningListAttemptHistoryUrl = (params) => {
893
+ const normalizedParams = new URLSearchParams();
894
+ Object.entries(params || {}).forEach(([key, value]) => {
895
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
896
+ });
897
+ const stringifiedParams = normalizedParams.toString();
898
+ return stringifiedParams.length > 0 ? `/learning/history/attempts?${stringifiedParams}` : `/learning/history/attempts`;
899
+ };
900
+ /**
901
+ * Returns only the effective profile's attempts, ordered by startedAt descending then attemptId descending. assessment_id optionally filters this history; it never changes ownership. Historical records are retained evidence and cannot be resumed. Scores are percentages serialized as decimal strings; null means no score is available.
902
+ * @summary List the profile's native and historical attempts
903
+ */
904
+ const learningListAttemptHistory = async (params, options) => {
905
+ return request(getLearningListAttemptHistoryUrl(params), {
906
+ ...options,
907
+ method: "GET"
908
+ });
909
+ };
910
+ const getLearningListAttemptHistoryQueryKey = (params) => {
911
+ return [`/learning/history/attempts`, ...params ? [params] : []];
912
+ };
913
+ const getLearningListAttemptHistoryQueryOptions = (params, options) => {
914
+ const { query: queryOptions, request: requestOptions } = options ?? {};
915
+ const queryKey = queryOptions?.queryKey ?? getLearningListAttemptHistoryQueryKey(params);
916
+ const queryFn = ({ signal }) => learningListAttemptHistory(params, {
917
+ signal,
918
+ ...requestOptions
919
+ });
920
+ return {
921
+ queryKey,
922
+ queryFn,
923
+ ...queryOptions
924
+ };
925
+ };
926
+ /**
927
+ * @summary List the profile's native and historical attempts
928
+ */
929
+ function useLearningListAttemptHistory(params, options, queryClient) {
930
+ const queryOptions = getLearningListAttemptHistoryQueryOptions(params, options);
931
+ const query = useQuery(queryOptions, queryClient);
932
+ return withQueryKey(query, queryOptions.queryKey);
933
+ }
934
+ const getLearningAttemptEvidenceUrl = (attemptId) => {
935
+ return `/learning/history/attempts/${attemptId}/evidence`;
936
+ };
937
+ /**
938
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Source flags and counters are reported evidence, not newly computed grades. Missing dates, links and scoring remain null; a recorded completion flag does not establish a native pass result. attemptId must identify an historical attempt. evidenceBasis distinguishes source_master_session counters from a source_session success flag. Counts describe linked recorded rows, not a reconstructed test definition. startedAt is the recorded attempt timestamp; unavailable completion or expiry dates remain null.
939
+ * @summary Read my historical assessment attempt evidence
940
+ */
941
+ const learningAttemptEvidence = async (attemptId, options) => {
942
+ return request(getLearningAttemptEvidenceUrl(attemptId), {
943
+ ...options,
944
+ method: "GET"
945
+ });
946
+ };
947
+ const getLearningAttemptEvidenceQueryKey = (attemptId) => {
948
+ return [`/learning/history/attempts/${attemptId}/evidence`];
949
+ };
950
+ const getLearningAttemptEvidenceQueryOptions = (attemptId, options) => {
951
+ const { query: queryOptions, request: requestOptions } = options ?? {};
952
+ const queryKey = queryOptions?.queryKey ?? getLearningAttemptEvidenceQueryKey(attemptId);
953
+ const queryFn = ({ signal }) => learningAttemptEvidence(attemptId, {
954
+ signal,
955
+ ...requestOptions
956
+ });
957
+ return {
958
+ queryKey,
959
+ queryFn,
960
+ enabled: attemptId !== null && attemptId !== void 0,
961
+ ...queryOptions
962
+ };
963
+ };
964
+ /**
965
+ * @summary Read my historical assessment attempt evidence
966
+ */
967
+ function useLearningAttemptEvidence(attemptId, options, queryClient) {
968
+ const queryOptions = getLearningAttemptEvidenceQueryOptions(attemptId, options);
969
+ const query = useQuery(queryOptions, queryClient);
970
+ return withQueryKey(query, queryOptions.queryKey);
971
+ }
972
+ const getLearningHistoricalSelectedPagesUrl = (attemptId, params) => {
973
+ const normalizedParams = new URLSearchParams();
974
+ Object.entries(params || {}).forEach(([key, value]) => {
975
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
976
+ });
977
+ const stringifiedParams = normalizedParams.toString();
978
+ return stringifiedParams.length > 0 ? `/learning/history/attempts/${attemptId}/selected-pages?${stringifiedParams}` : `/learning/history/attempts/${attemptId}/selected-pages`;
979
+ };
980
+ /**
981
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Lists the retained selected-page set, ordered by page ID and paginated with one-based page/limit. A selected page is evidence of inclusion, not proof it was viewed, answered or passed. Detailed page history is available separately. No questions or correct answers are reconstructed from this set.
982
+ * @summary List pages selected for my historical attempt
983
+ */
984
+ const learningHistoricalSelectedPages = async (attemptId, params, options) => {
985
+ return request(getLearningHistoricalSelectedPagesUrl(attemptId, params), {
986
+ ...options,
987
+ method: "GET"
988
+ });
989
+ };
990
+ const getLearningHistoricalSelectedPagesQueryKey = (attemptId, params) => {
991
+ return [`/learning/history/attempts/${attemptId}/selected-pages`, ...params ? [params] : []];
992
+ };
993
+ const getLearningHistoricalSelectedPagesQueryOptions = (attemptId, params, options) => {
994
+ const { query: queryOptions, request: requestOptions } = options ?? {};
995
+ const queryKey = queryOptions?.queryKey ?? getLearningHistoricalSelectedPagesQueryKey(attemptId, params);
996
+ const queryFn = ({ signal }) => learningHistoricalSelectedPages(attemptId, params, {
997
+ signal,
998
+ ...requestOptions
999
+ });
1000
+ return {
1001
+ queryKey,
1002
+ queryFn,
1003
+ enabled: attemptId !== null && attemptId !== void 0,
1004
+ ...queryOptions
1005
+ };
1006
+ };
1007
+ /**
1008
+ * @summary List pages selected for my historical attempt
1009
+ */
1010
+ function useLearningHistoricalSelectedPages(attemptId, params, options, queryClient) {
1011
+ const queryOptions = getLearningHistoricalSelectedPagesQueryOptions(attemptId, params, options);
1012
+ const query = useQuery(queryOptions, queryClient);
1013
+ return withQueryKey(query, queryOptions.queryKey);
1014
+ }
1015
+ const getLearningPageEvidenceUrl = (params) => {
1016
+ const normalizedParams = new URLSearchParams();
1017
+ Object.entries(params || {}).forEach(([key, value]) => {
1018
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
1019
+ });
1020
+ const stringifiedParams = normalizedParams.toString();
1021
+ return stringifiedParams.length > 0 ? `/learning/history/pages?${stringifiedParams}` : `/learning/history/pages`;
1022
+ };
1023
+ /**
1024
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Source flags and counters are reported evidence, not newly computed grades. Missing dates, links and scoring remain null; a recorded completion flag does not establish a native pass result. attemptId selects an owned historical attempt; unlinkedOnly=true selects rows with no stored attempt link and cannot be combined with attemptId. Optional object filters apply within that same ownership scope. Results are ordered by history ID descending and paginated after filtering. pageId optionally narrows to one local page identity. A returned attemptId is exposed only when it links to an owned historical attempt. responseAvailable indicates retained response evidence, not whether the bounded detail endpoint will return its serialized bytes.
1025
+ * @summary List my recorded page evidence
1026
+ */
1027
+ const learningPageEvidence = async (params, options) => {
1028
+ return request(getLearningPageEvidenceUrl(params), {
1029
+ ...options,
1030
+ method: "GET"
1031
+ });
1032
+ };
1033
+ const getLearningPageEvidenceQueryKey = (params) => {
1034
+ return [`/learning/history/pages`, ...params ? [params] : []];
1035
+ };
1036
+ const getLearningPageEvidenceQueryOptions = (params, options) => {
1037
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1038
+ const queryKey = queryOptions?.queryKey ?? getLearningPageEvidenceQueryKey(params);
1039
+ const queryFn = ({ signal }) => learningPageEvidence(params, {
1040
+ signal,
1041
+ ...requestOptions
1042
+ });
1043
+ return {
1044
+ queryKey,
1045
+ queryFn,
1046
+ ...queryOptions
1047
+ };
1048
+ };
1049
+ /**
1050
+ * @summary List my recorded page evidence
1051
+ */
1052
+ function useLearningPageEvidence(params, options, queryClient) {
1053
+ const queryOptions = getLearningPageEvidenceQueryOptions(params, options);
1054
+ const query = useQuery(queryOptions, queryClient);
1055
+ return withQueryKey(query, queryOptions.queryKey);
1056
+ }
1057
+ const getLearningPageEvidenceDetailUrl = (historyId) => {
1058
+ return `/learning/history/pages/${historyId}`;
1059
+ };
1060
+ /**
1061
+ * Returns evidence owned by the effective profile and rejects support impersonation. Resource identifiers do not authorize access to another learner. Source flags and counters are reported evidence, not newly computed grades. Missing dates, links and scoring remain null; a recorded completion flag does not establish a native pass result. Returns opaque PHP-serialized answer text only when retained as source master-selection evidence and at most 65,536 UTF-8 bytes. Larger responses retain encoding and byte count but set responseOmitted=true and serializedAnswers=null. A missing response instead has null encoding/count and responseOmitted=false. Source text is evidence, never a native answer request or trusted executable serialization.
1062
+ * @summary Read my historical page response evidence
1063
+ */
1064
+ const learningPageEvidenceDetail = async (historyId, options) => {
1065
+ return request(getLearningPageEvidenceDetailUrl(historyId), {
1066
+ ...options,
1067
+ method: "GET"
1068
+ });
1069
+ };
1070
+ const getLearningPageEvidenceDetailQueryKey = (historyId) => {
1071
+ return [`/learning/history/pages/${historyId}`];
1072
+ };
1073
+ const getLearningPageEvidenceDetailQueryOptions = (historyId, options) => {
1074
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1075
+ const queryKey = queryOptions?.queryKey ?? getLearningPageEvidenceDetailQueryKey(historyId);
1076
+ const queryFn = ({ signal }) => learningPageEvidenceDetail(historyId, {
1077
+ signal,
1078
+ ...requestOptions
1079
+ });
1080
+ return {
1081
+ queryKey,
1082
+ queryFn,
1083
+ enabled: historyId !== null && historyId !== void 0,
1084
+ ...queryOptions
1085
+ };
1086
+ };
1087
+ /**
1088
+ * @summary Read my historical page response evidence
1089
+ */
1090
+ function useLearningPageEvidenceDetail(historyId, options, queryClient) {
1091
+ const queryOptions = getLearningPageEvidenceDetailQueryOptions(historyId, options);
1092
+ const query = useQuery(queryOptions, queryClient);
1093
+ return withQueryKey(query, queryOptions.queryKey);
1094
+ }
1095
+ const getLearningListScoreHistoryUrl = (params) => {
1096
+ const normalizedParams = new URLSearchParams();
1097
+ Object.entries(params || {}).forEach(([key, value]) => {
1098
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
1099
+ });
1100
+ const stringifiedParams = normalizedParams.toString();
1101
+ return stringifiedParams.length > 0 ? `/learning/history/scores?${stringifiedParams}` : `/learning/history/scores`;
1102
+ };
1103
+ /**
1104
+ * Returns one stored summary per assessment in the effective profile's history, newest creation time first with assessmentId as tie-breaker. A native completion replaces its assessment's summary; this is not a best-score leaderboard. An imported aggregate may have historical=true and attemptId=null because no attempt evidence exists. assessment_id restricts the list to that assessment.
1105
+ * @summary List the profile's assessment score summaries
1106
+ */
1107
+ const learningListScoreHistory = async (params, options) => {
1108
+ return request(getLearningListScoreHistoryUrl(params), {
1109
+ ...options,
1110
+ method: "GET"
1111
+ });
1112
+ };
1113
+ const getLearningListScoreHistoryQueryKey = (params) => {
1114
+ return [`/learning/history/scores`, ...params ? [params] : []];
1115
+ };
1116
+ const getLearningListScoreHistoryQueryOptions = (params, options) => {
1117
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1118
+ const queryKey = queryOptions?.queryKey ?? getLearningListScoreHistoryQueryKey(params);
1119
+ const queryFn = ({ signal }) => learningListScoreHistory(params, {
1120
+ signal,
1121
+ ...requestOptions
1122
+ });
1123
+ return {
1124
+ queryKey,
1125
+ queryFn,
1126
+ ...queryOptions
1127
+ };
1128
+ };
1129
+ /**
1130
+ * @summary List the profile's assessment score summaries
1131
+ */
1132
+ function useLearningListScoreHistory(params, options, queryClient) {
1133
+ const queryOptions = getLearningListScoreHistoryQueryOptions(params, options);
1134
+ const query = useQuery(queryOptions, queryClient);
1135
+ return withQueryKey(query, queryOptions.queryKey);
1136
+ }
1137
+ const getLearningOpenLessonUrl = (lessonId) => {
1138
+ return `/learning/lessons/${lessonId}/open`;
1139
+ };
1140
+ /**
1141
+ * With sessionId, checks this profile's open course session and edition, renews its lease and selects the lesson for subsequent activity ticks. Without sessionId, both course previews and this lesson's freePreview must be enabled. Returns authorized media delivery URLs or HTML, public attachments and any vocabulary; corrections remain attempt-scoped. Delivery URLs may expire, so request fresh resources when reopening. A preview does not enroll the profile or record full-course consumption.
1142
+ * @summary Open lesson resources in a session or free preview
1143
+ */
1144
+ const learningOpenLesson = async (lessonId, learningLessonOpenWrite, options) => {
1145
+ const getHeaders = (h) => {
1146
+ if (!h) return {};
1147
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1148
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1149
+ const headers = {};
1150
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1151
+ return headers;
1152
+ };
1153
+ return request(getLearningOpenLessonUrl(lessonId), {
1154
+ ...options,
1155
+ method: "POST",
1156
+ headers: {
1157
+ "Content-Type": "application/json",
1158
+ ...getHeaders(options?.headers)
1159
+ },
1160
+ body: JSON.stringify(learningLessonOpenWrite)
1161
+ });
1162
+ };
1163
+ const getLearningOpenLessonMutationKey = () => ["learningOpenLesson"];
1164
+ const getLearningOpenLessonMutationOptions = (options) => {
1165
+ const mutationKey = getLearningOpenLessonMutationKey();
1166
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1167
+ ...options,
1168
+ mutation: {
1169
+ ...options.mutation,
1170
+ mutationKey
1171
+ }
1172
+ } : {
1173
+ mutation: { mutationKey },
1174
+ request: void 0
1175
+ };
1176
+ const mutationFn = (props) => {
1177
+ const { lessonId, data } = props ?? {};
1178
+ return learningOpenLesson(lessonId, data, requestOptions);
1179
+ };
1180
+ return {
1181
+ mutationFn,
1182
+ ...mutationOptions
1183
+ };
1184
+ };
1185
+ /**
1186
+ * @summary Open lesson resources in a session or free preview
1187
+ */
1188
+ const useLearningOpenLesson = (options, queryClient) => {
1189
+ return useMutation(getLearningOpenLessonMutationOptions(options), queryClient);
1190
+ };
1191
+ const getLearningUpdateProgressUrl = (lessonId) => {
1192
+ return `/learning/lessons/${lessonId}/progress`;
1193
+ };
1194
+ /**
1195
+ * Requires full access to the profile's selected course edition and creates enrollment if needed. Omit note to retain it; send null to clear it. positionSeconds is allowed only for resource lessons and cannot exceed a known duration. completed=true marks only a resource lesson complete; assessment and vocabulary lessons require their own completion workflow. Completion is retained on later completed=false writes. Updates the resume lesson and recomputes course progress from required lessons.
1196
+ * @summary Save lesson notes, playback position or resource completion
1197
+ */
1198
+ const learningUpdateProgress = async (lessonId, lessonProgressWrite, options) => {
1199
+ const getHeaders = (h) => {
1200
+ if (!h) return {};
1201
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1202
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1203
+ const headers = {};
1204
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1205
+ return headers;
1206
+ };
1207
+ return request(getLearningUpdateProgressUrl(lessonId), {
1208
+ ...options,
1209
+ method: "PUT",
1210
+ headers: {
1211
+ "Content-Type": "application/json",
1212
+ ...getHeaders(options?.headers)
1213
+ },
1214
+ body: JSON.stringify(lessonProgressWrite)
1215
+ });
1216
+ };
1217
+ const getLearningUpdateProgressMutationKey = () => ["learningUpdateProgress"];
1218
+ const getLearningUpdateProgressMutationOptions = (options) => {
1219
+ const mutationKey = getLearningUpdateProgressMutationKey();
1220
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1221
+ ...options,
1222
+ mutation: {
1223
+ ...options.mutation,
1224
+ mutationKey
1225
+ }
1226
+ } : {
1227
+ mutation: { mutationKey },
1228
+ request: void 0
1229
+ };
1230
+ const mutationFn = (props) => {
1231
+ const { lessonId, data } = props ?? {};
1232
+ return learningUpdateProgress(lessonId, data, requestOptions);
1233
+ };
1234
+ return {
1235
+ mutationFn,
1236
+ ...mutationOptions
1237
+ };
1238
+ };
1239
+ /**
1240
+ * @summary Save lesson notes, playback position or resource completion
1241
+ */
1242
+ const useLearningUpdateProgress = (options, queryClient) => {
1243
+ return useMutation(getLearningUpdateProgressMutationOptions(options), queryClient);
1244
+ };
1245
+ const getLearningPathIntroductionUrl = (pathId) => {
1246
+ return `/learning/paths/${pathId}/introduction`;
1247
+ };
1248
+ /**
1249
+ * Returns a delivery descriptor, not the media bytes. The path must be active and at least one of its steps visible through the effective profile's catalogue access. Follow the returned URL promptly; delivery URLs may be temporary.
1250
+ * @summary Get a visible path's introduction resource
1251
+ */
1252
+ const learningPathIntroduction = async (pathId, options) => {
1253
+ return request(getLearningPathIntroductionUrl(pathId), {
1254
+ ...options,
1255
+ method: "GET"
1256
+ });
1257
+ };
1258
+ const getLearningPathIntroductionQueryKey = (pathId) => {
1259
+ return [`/learning/paths/${pathId}/introduction`];
1260
+ };
1261
+ const getLearningPathIntroductionQueryOptions = (pathId, options) => {
1262
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1263
+ const queryKey = queryOptions?.queryKey ?? getLearningPathIntroductionQueryKey(pathId);
1264
+ const queryFn = ({ signal }) => learningPathIntroduction(pathId, {
1265
+ signal,
1266
+ ...requestOptions
1267
+ });
1268
+ return {
1269
+ queryKey,
1270
+ queryFn,
1271
+ enabled: pathId !== null && pathId !== void 0,
1272
+ ...queryOptions
1273
+ };
1274
+ };
1275
+ /**
1276
+ * @summary Get a visible path's introduction resource
1277
+ */
1278
+ function useLearningPathIntroduction(pathId, options, queryClient) {
1279
+ const queryOptions = getLearningPathIntroductionQueryOptions(pathId, options);
1280
+ const query = useQuery(queryOptions, queryClient);
1281
+ return withQueryKey(query, queryOptions.queryKey);
1282
+ }
1283
+ const getLearningOpenPathStepUrl = (pathId) => {
1284
+ return `/learning/paths/${pathId}/open`;
1285
+ };
1286
+ /**
1287
+ * Sets the effective profile's current position to an active path's visible step, creating progress on first use. contentId must be a member of the path and pass existing catalogue visibility checks. This records navigation; the response is not a course reader payload. Support impersonation is rejected.
1288
+ * @summary Record my selected path step
1289
+ */
1290
+ const learningOpenPathStep = async (pathId, learningPathOpenWrite, options) => {
1291
+ const getHeaders = (h) => {
1292
+ if (!h) return {};
1293
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1294
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1295
+ const headers = {};
1296
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1297
+ return headers;
1298
+ };
1299
+ return request(getLearningOpenPathStepUrl(pathId), {
1300
+ ...options,
1301
+ method: "POST",
1302
+ headers: {
1303
+ "Content-Type": "application/json",
1304
+ ...getHeaders(options?.headers)
1305
+ },
1306
+ body: JSON.stringify(learningPathOpenWrite)
1307
+ });
1308
+ };
1309
+ const getLearningOpenPathStepMutationKey = () => ["learningOpenPathStep"];
1310
+ const getLearningOpenPathStepMutationOptions = (options) => {
1311
+ const mutationKey = getLearningOpenPathStepMutationKey();
1312
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1313
+ ...options,
1314
+ mutation: {
1315
+ ...options.mutation,
1316
+ mutationKey
1317
+ }
1318
+ } : {
1319
+ mutation: { mutationKey },
1320
+ request: void 0
1321
+ };
1322
+ const mutationFn = (props) => {
1323
+ const { pathId, data } = props ?? {};
1324
+ return learningOpenPathStep(pathId, data, requestOptions);
1325
+ };
1326
+ return {
1327
+ mutationFn,
1328
+ ...mutationOptions
1329
+ };
1330
+ };
1331
+ /**
1332
+ * @summary Record my selected path step
1333
+ */
1334
+ const useLearningOpenPathStep = (options, queryClient) => {
1335
+ return useMutation(getLearningOpenPathStepMutationOptions(options), queryClient);
1336
+ };
1337
+ const getLearningReadPathProgressUrl = (pathId) => {
1338
+ return `/learning/paths/${pathId}/progress`;
1339
+ };
1340
+ /**
1341
+ * Returns only the effective profile's recorded position and does not start the path. started=false means no progress row exists, including for an unknown path ID. position is zero-based. currentContentId is null when no recorded step is currently visible; a stored position may survive later curation changes.
1342
+ * @summary Read my current position in a path
1343
+ */
1344
+ const learningReadPathProgress = async (pathId, options) => {
1345
+ return request(getLearningReadPathProgressUrl(pathId), {
1346
+ ...options,
1347
+ method: "GET"
1348
+ });
1349
+ };
1350
+ const getLearningReadPathProgressQueryKey = (pathId) => {
1351
+ return [`/learning/paths/${pathId}/progress`];
1352
+ };
1353
+ const getLearningReadPathProgressQueryOptions = (pathId, options) => {
1354
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1355
+ const queryKey = queryOptions?.queryKey ?? getLearningReadPathProgressQueryKey(pathId);
1356
+ const queryFn = ({ signal }) => learningReadPathProgress(pathId, {
1357
+ signal,
1358
+ ...requestOptions
1359
+ });
1360
+ return {
1361
+ queryKey,
1362
+ queryFn,
1363
+ enabled: pathId !== null && pathId !== void 0,
1364
+ ...queryOptions
1365
+ };
1366
+ };
1367
+ /**
1368
+ * @summary Read my current position in a path
1369
+ */
1370
+ function useLearningReadPathProgress(pathId, options, queryClient) {
1371
+ const queryOptions = getLearningReadPathProgressQueryOptions(pathId, options);
1372
+ const query = useQuery(queryOptions, queryClient);
1373
+ return withQueryKey(query, queryOptions.queryKey);
1374
+ }
1375
+ const getLearningCloseSessionUrl = (sessionId) => {
1376
+ return `/learning/sessions/${sessionId}`;
1377
+ };
1378
+ /**
1379
+ * Closes only a session owned by the effective profile and records closedAt. Repeating the close returns the same closed session. Enrollment, answers and lesson progress are retained; this operation does not mark a lesson complete.
1380
+ * @summary Close a course session and its consumption lease
1381
+ */
1382
+ const learningCloseSession = async (sessionId, options) => {
1383
+ return request(getLearningCloseSessionUrl(sessionId), {
1384
+ ...options,
1385
+ method: "DELETE"
1386
+ });
1387
+ };
1388
+ const getLearningCloseSessionMutationKey = () => ["learningCloseSession"];
1389
+ const getLearningCloseSessionMutationOptions = (options) => {
1390
+ const mutationKey = getLearningCloseSessionMutationKey();
1391
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1392
+ ...options,
1393
+ mutation: {
1394
+ ...options.mutation,
1395
+ mutationKey
1396
+ }
1397
+ } : {
1398
+ mutation: { mutationKey },
1399
+ request: void 0
1400
+ };
1401
+ const mutationFn = (props) => {
1402
+ const { sessionId } = props ?? {};
1403
+ return learningCloseSession(sessionId, requestOptions);
1404
+ };
1405
+ return {
1406
+ mutationFn,
1407
+ ...mutationOptions
1408
+ };
1409
+ };
1410
+ /**
1411
+ * @summary Close a course session and its consumption lease
1412
+ */
1413
+ const useLearningCloseSession = (options, queryClient) => {
1414
+ return useMutation(getLearningCloseSessionMutationOptions(options), queryClient);
1415
+ };
1416
+ const getLearningRecordActivityUrl = (sessionId) => {
1417
+ return `/learning/sessions/${sessionId}/activity`;
1418
+ };
1419
+ /**
1420
+ * Requires this profile's open session and the lesson most recently selected with the lesson-open operation. Renews the consumption lease. active=true records server-observed elapsed time since the previous heartbeat, capped at 60 seconds per tick; active=false moves the clock forward without adding time. activeSeconds is cumulative seconds, separate from lesson completion and playback position. Heartbeats have no request key; send them only for current activity.
1421
+ * @summary Record an activity heartbeat for the selected lesson
1422
+ */
1423
+ const learningRecordActivity = async (sessionId, learningActivityWrite, options) => {
1424
+ const getHeaders = (h) => {
1425
+ if (!h) return {};
1426
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1427
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1428
+ const headers = {};
1429
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1430
+ return headers;
1431
+ };
1432
+ return request(getLearningRecordActivityUrl(sessionId), {
1433
+ ...options,
1434
+ method: "PUT",
1435
+ headers: {
1436
+ "Content-Type": "application/json",
1437
+ ...getHeaders(options?.headers)
1438
+ },
1439
+ body: JSON.stringify(learningActivityWrite)
1440
+ });
1441
+ };
1442
+ const getLearningRecordActivityMutationKey = () => ["learningRecordActivity"];
1443
+ const getLearningRecordActivityMutationOptions = (options) => {
1444
+ const mutationKey = getLearningRecordActivityMutationKey();
1445
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1446
+ ...options,
1447
+ mutation: {
1448
+ ...options.mutation,
1449
+ mutationKey
1450
+ }
1451
+ } : {
1452
+ mutation: { mutationKey },
1453
+ request: void 0
1454
+ };
1455
+ const mutationFn = (props) => {
1456
+ const { sessionId, data } = props ?? {};
1457
+ return learningRecordActivity(sessionId, data, requestOptions);
1458
+ };
1459
+ return {
1460
+ mutationFn,
1461
+ ...mutationOptions
1462
+ };
1463
+ };
1464
+ /**
1465
+ * @summary Record an activity heartbeat for the selected lesson
1466
+ */
1467
+ const useLearningRecordActivity = (options, queryClient) => {
1468
+ return useMutation(getLearningRecordActivityMutationOptions(options), queryClient);
1469
+ };
1470
+ const getLearningUploadBytesUrl = (uploadId) => {
1471
+ return `/learning/uploads/${uploadId}/body`;
1472
+ };
1473
+ /**
1474
+ * Send an authenticated raw binary PUT, not multipart or JSON, to the reservation's uploadUrl before expiresAt. The byte count must exactly match sizeBytes; file signatures are checked against the reserved MIME type and captions must be valid UTF-8 WebVTT. Ownership and upload purpose are rechecked. A same-byte replay before expiry returns the existing immutable asset; different bytes cannot overwrite it. The JSON response contains the asset ID for a course definition or reflection answer, without issuing a delivery URL.
1475
+ * @summary Upload the exact bytes of a reserved file
1476
+ */
1477
+ const learningUploadBytes = async (uploadId, learningUploadBytesBody, options) => {
1478
+ const getHeaders = (h) => {
1479
+ if (!h) return {};
1480
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1481
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1482
+ const headers = {};
1483
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1484
+ return headers;
1485
+ };
1486
+ return request(getLearningUploadBytesUrl(uploadId), {
1487
+ ...options,
1488
+ method: "PUT",
1489
+ headers: {
1490
+ "Content-Type": "application/octet-stream",
1491
+ ...getHeaders(options?.headers)
1492
+ },
1493
+ body: learningUploadBytesBody
1494
+ });
1495
+ };
1496
+ const getLearningUploadBytesMutationKey = () => ["learningUploadBytes"];
1497
+ const getLearningUploadBytesMutationOptions = (options) => {
1498
+ const mutationKey = getLearningUploadBytesMutationKey();
1499
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1500
+ ...options,
1501
+ mutation: {
1502
+ ...options.mutation,
1503
+ mutationKey
1504
+ }
1505
+ } : {
1506
+ mutation: { mutationKey },
1507
+ request: void 0
1508
+ };
1509
+ const mutationFn = (props) => {
1510
+ const { uploadId, data } = props ?? {};
1511
+ return learningUploadBytes(uploadId, data, requestOptions);
1512
+ };
1513
+ return {
1514
+ mutationFn,
1515
+ ...mutationOptions
1516
+ };
1517
+ };
1518
+ /**
1519
+ * @summary Upload the exact bytes of a reserved file
1520
+ */
1521
+ const useLearningUploadBytes = (options, queryClient) => {
1522
+ return useMutation(getLearningUploadBytesMutationOptions(options), queryClient);
1523
+ };
1524
+ const getLearningReadVocabularyUrl = (vocabularyId, params) => {
1525
+ const normalizedParams = new URLSearchParams();
1526
+ Object.entries(params || {}).forEach(([key, value]) => {
1527
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
1528
+ });
1529
+ const stringifiedParams = normalizedParams.toString();
1530
+ return stringifiedParams.length > 0 ? `/learning/vocabularies/${vocabularyId}?${stringifiedParams}` : `/learning/vocabularies/${vocabularyId}`;
1531
+ };
1532
+ /**
1533
+ * lesson_id must identify a lesson using this vocabulary directly or as an attachment. Full reads return the profile's position and completion evidence. preview=true additionally requires that lesson's free-preview permission and omits saved personal progress. Entries are ordered by position then entry ID; term media IDs must be resolved through the vocabulary resource operation.
1534
+ * @summary Read vocabulary through an authorized lesson
1535
+ */
1536
+ const learningReadVocabulary = async (vocabularyId, params, options) => {
1537
+ return request(getLearningReadVocabularyUrl(vocabularyId, params), {
1538
+ ...options,
1539
+ method: "GET"
1540
+ });
1541
+ };
1542
+ const getLearningReadVocabularyQueryKey = (vocabularyId, params) => {
1543
+ return [`/learning/vocabularies/${vocabularyId}`, ...params ? [params] : []];
1544
+ };
1545
+ const getLearningReadVocabularyQueryOptions = (vocabularyId, params, options) => {
1546
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1547
+ const queryKey = queryOptions?.queryKey ?? getLearningReadVocabularyQueryKey(vocabularyId, params);
1548
+ const queryFn = ({ signal }) => learningReadVocabulary(vocabularyId, params, {
1549
+ signal,
1550
+ ...requestOptions
1551
+ });
1552
+ return {
1553
+ queryKey,
1554
+ queryFn,
1555
+ enabled: vocabularyId !== null && vocabularyId !== void 0,
1556
+ ...queryOptions
1557
+ };
1558
+ };
1559
+ /**
1560
+ * @summary Read vocabulary through an authorized lesson
1561
+ */
1562
+ function useLearningReadVocabulary(vocabularyId, params, options, queryClient) {
1563
+ const queryOptions = getLearningReadVocabularyQueryOptions(vocabularyId, params, options);
1564
+ const query = useQuery(queryOptions, queryClient);
1565
+ return withQueryKey(query, queryOptions.queryKey);
1566
+ }
1567
+ const getLearningVocabularyResourceUrl = (vocabularyId, assetId, params) => {
1568
+ const normalizedParams = new URLSearchParams();
1569
+ Object.entries(params || {}).forEach(([key, value]) => {
1570
+ if (value !== void 0) normalizedParams.append(key, value === null ? "null" : String(value));
1571
+ });
1572
+ const stringifiedParams = normalizedParams.toString();
1573
+ return stringifiedParams.length > 0 ? `/learning/vocabularies/${vocabularyId}/assets/${assetId}?${stringifiedParams}` : `/learning/vocabularies/${vocabularyId}/assets/${assetId}`;
1574
+ };
1575
+ /**
1576
+ * Checks vocabulary and lesson context exactly as the vocabulary read operation, including preview permission when preview=true. assetId must be audio or image referenced by a term or translation in this vocabulary; knowing a media ID alone grants no access. Returns delivery metadata with a potentially expiring URL.
1577
+ * @summary Resolve a vocabulary term's audio or image
1578
+ */
1579
+ const learningVocabularyResource = async (vocabularyId, assetId, params, options) => {
1580
+ return request(getLearningVocabularyResourceUrl(vocabularyId, assetId, params), {
1581
+ ...options,
1582
+ method: "GET"
1583
+ });
1584
+ };
1585
+ const getLearningVocabularyResourceQueryKey = (vocabularyId, assetId, params) => {
1586
+ return [`/learning/vocabularies/${vocabularyId}/assets/${assetId}`, ...params ? [params] : []];
1587
+ };
1588
+ const getLearningVocabularyResourceQueryOptions = (vocabularyId, assetId, params, options) => {
1589
+ const { query: queryOptions, request: requestOptions } = options ?? {};
1590
+ const queryKey = queryOptions?.queryKey ?? getLearningVocabularyResourceQueryKey(vocabularyId, assetId, params);
1591
+ const queryFn = ({ signal }) => learningVocabularyResource(vocabularyId, assetId, params, {
1592
+ signal,
1593
+ ...requestOptions
1594
+ });
1595
+ return {
1596
+ queryKey,
1597
+ queryFn,
1598
+ enabled: vocabularyId !== null && vocabularyId !== void 0 && assetId !== null && assetId !== void 0,
1599
+ ...queryOptions
1600
+ };
1601
+ };
1602
+ /**
1603
+ * @summary Resolve a vocabulary term's audio or image
1604
+ */
1605
+ function useLearningVocabularyResource(vocabularyId, assetId, params, options, queryClient) {
1606
+ const queryOptions = getLearningVocabularyResourceQueryOptions(vocabularyId, assetId, params, options);
1607
+ const query = useQuery(queryOptions, queryClient);
1608
+ return withQueryKey(query, queryOptions.queryKey);
1609
+ }
1610
+ const getLearningUpdateVocabularyUrl = (vocabularyId) => {
1611
+ return `/learning/vocabularies/${vocabularyId}/progress`;
1612
+ };
1613
+ /**
1614
+ * Requires full access through lessonId and creates course enrollment if needed. position is a cursor from 0 through the entry count; completed=true requires a nonempty vocabulary and position exactly equal to its entry count. Completion is retained on subsequent writes. Completing the lesson's primary vocabulary also completes that lesson; completing an attached vocabulary does not. Updates the resume lesson and recomputes required-lesson progress.
1615
+ * @summary Save vocabulary position or completion
1616
+ */
1617
+ const learningUpdateVocabulary = async (vocabularyId, vocabularyProgressWrite, options) => {
1618
+ const getHeaders = (h) => {
1619
+ if (!h) return {};
1620
+ if (h instanceof Headers) return Object.fromEntries(h.entries());
1621
+ if (Symbol.iterator in h) return Object.fromEntries(Array.from(h, (entry) => Array.from(entry)));
1622
+ const headers = {};
1623
+ for (const [name, value] of Object.entries(h)) if (value !== void 0) headers[name] = value;
1624
+ return headers;
1625
+ };
1626
+ return request(getLearningUpdateVocabularyUrl(vocabularyId), {
1627
+ ...options,
1628
+ method: "PUT",
1629
+ headers: {
1630
+ "Content-Type": "application/json",
1631
+ ...getHeaders(options?.headers)
1632
+ },
1633
+ body: JSON.stringify(vocabularyProgressWrite)
1634
+ });
1635
+ };
1636
+ const getLearningUpdateVocabularyMutationKey = () => ["learningUpdateVocabulary"];
1637
+ const getLearningUpdateVocabularyMutationOptions = (options) => {
1638
+ const mutationKey = getLearningUpdateVocabularyMutationKey();
1639
+ const { mutation: mutationOptions, request: requestOptions } = options ? options.mutation && "mutationKey" in options.mutation && options.mutation.mutationKey ? options : {
1640
+ ...options,
1641
+ mutation: {
1642
+ ...options.mutation,
1643
+ mutationKey
1644
+ }
1645
+ } : {
1646
+ mutation: { mutationKey },
1647
+ request: void 0
1648
+ };
1649
+ const mutationFn = (props) => {
1650
+ const { vocabularyId, data } = props ?? {};
1651
+ return learningUpdateVocabulary(vocabularyId, data, requestOptions);
1652
+ };
1653
+ return {
1654
+ mutationFn,
1655
+ ...mutationOptions
1656
+ };
1657
+ };
1658
+ /**
1659
+ * @summary Save vocabulary position or completion
1660
+ */
1661
+ const useLearningUpdateVocabulary = (options, queryClient) => {
1662
+ return useMutation(getLearningUpdateVocabularyMutationOptions(options), queryClient);
1663
+ };
1664
+ //#endregion
1665
+ export { getLearningAbandonAttemptMutationKey, getLearningAbandonAttemptMutationOptions, getLearningAbandonAttemptUrl, getLearningAnswerQuestionMutationKey, getLearningAnswerQuestionMutationOptions, getLearningAnswerQuestionUrl, getLearningAnswerSelectionDetailQueryKey, getLearningAnswerSelectionDetailQueryOptions, getLearningAnswerSelectionDetailUrl, getLearningAnswerSelectionEvidenceQueryKey, getLearningAnswerSelectionEvidenceQueryOptions, getLearningAnswerSelectionEvidenceUrl, getLearningAttemptEvidenceQueryKey, getLearningAttemptEvidenceQueryOptions, getLearningAttemptEvidenceUrl, getLearningCloseSessionMutationKey, getLearningCloseSessionMutationOptions, getLearningCloseSessionUrl, getLearningDownloadCertificateQueryKey, getLearningDownloadCertificateQueryOptions, getLearningDownloadCertificateUrl, getLearningEnrollMutationKey, getLearningEnrollMutationOptions, getLearningEnrollUrl, getLearningFinishAttemptMutationKey, getLearningFinishAttemptMutationOptions, getLearningFinishAttemptUrl, getLearningHistoricalSelectedPagesQueryKey, getLearningHistoricalSelectedPagesQueryOptions, getLearningHistoricalSelectedPagesUrl, getLearningIssueCertificateMutationKey, getLearningIssueCertificateMutationOptions, getLearningIssueCertificateUrl, getLearningListAttemptHistoryQueryKey, getLearningListAttemptHistoryQueryOptions, getLearningListAttemptHistoryUrl, getLearningListScoreHistoryQueryKey, getLearningListScoreHistoryQueryOptions, getLearningListScoreHistoryUrl, getLearningOpenLessonMutationKey, getLearningOpenLessonMutationOptions, getLearningOpenLessonUrl, getLearningOpenPathStepMutationKey, getLearningOpenPathStepMutationOptions, getLearningOpenPathStepUrl, getLearningPageEvidenceDetailQueryKey, getLearningPageEvidenceDetailQueryOptions, getLearningPageEvidenceDetailUrl, getLearningPageEvidenceQueryKey, getLearningPageEvidenceQueryOptions, getLearningPageEvidenceUrl, getLearningPathIntroductionQueryKey, getLearningPathIntroductionQueryOptions, getLearningPathIntroductionUrl, getLearningRateExercisePageMutationKey, getLearningRateExercisePageMutationOptions, getLearningRateExercisePageUrl, getLearningReadAttemptQueryKey, getLearningReadAttemptQueryOptions, getLearningReadAttemptResourceQueryKey, getLearningReadAttemptResourceQueryOptions, getLearningReadAttemptResourceUrl, getLearningReadAttemptUrl, getLearningReadCertificateQueryKey, getLearningReadCertificateQueryOptions, getLearningReadCertificateUrl, getLearningReadCourseQueryKey, getLearningReadCourseQueryOptions, getLearningReadCourseUrl, getLearningReadEnrollmentHistoryQueryKey, getLearningReadEnrollmentHistoryQueryOptions, getLearningReadEnrollmentHistoryUrl, getLearningReadPathProgressQueryKey, getLearningReadPathProgressQueryOptions, getLearningReadPathProgressUrl, getLearningReadVocabularyQueryKey, getLearningReadVocabularyQueryOptions, getLearningReadVocabularyUrl, getLearningRecordActivityMutationKey, getLearningRecordActivityMutationOptions, getLearningRecordActivityUrl, getLearningReserveCourseUploadMutationKey, getLearningReserveCourseUploadMutationOptions, getLearningReserveCourseUploadUrl, getLearningReserveExerciseUploadMutationKey, getLearningReserveExerciseUploadMutationOptions, getLearningReserveExerciseUploadUrl, getLearningStartAttemptMutationKey, getLearningStartAttemptMutationOptions, getLearningStartAttemptUrl, getLearningStartSessionMutationKey, getLearningStartSessionMutationOptions, getLearningStartSessionUrl, getLearningUpdateProgressMutationKey, getLearningUpdateProgressMutationOptions, getLearningUpdateProgressUrl, getLearningUpdateVocabularyMutationKey, getLearningUpdateVocabularyMutationOptions, getLearningUpdateVocabularyUrl, getLearningUpgradeCourseEditionMutationKey, getLearningUpgradeCourseEditionMutationOptions, getLearningUpgradeCourseEditionUrl, getLearningUploadBytesMutationKey, getLearningUploadBytesMutationOptions, getLearningUploadBytesUrl, getLearningVocabularyResourceQueryKey, getLearningVocabularyResourceQueryOptions, getLearningVocabularyResourceUrl, learningAbandonAttempt, learningAnswerQuestion, learningAnswerSelectionDetail, learningAnswerSelectionEvidence, learningAttemptEvidence, learningCloseSession, learningDownloadCertificate, learningEnroll, learningFinishAttempt, learningHistoricalSelectedPages, learningIssueCertificate, learningListAttemptHistory, learningListScoreHistory, learningOpenLesson, learningOpenPathStep, learningPageEvidence, learningPageEvidenceDetail, learningPathIntroduction, learningRateExercisePage, learningReadAttempt, learningReadAttemptResource, learningReadCertificate, learningReadCourse, learningReadEnrollmentHistory, learningReadPathProgress, learningReadVocabulary, learningRecordActivity, learningReserveCourseUpload, learningReserveExerciseUpload, learningStartAttempt, learningStartSession, learningUpdateProgress, learningUpdateVocabulary, learningUpgradeCourseEdition, learningUploadBytes, learningVocabularyResource, useLearningAbandonAttempt, useLearningAnswerQuestion, useLearningAnswerSelectionDetail, useLearningAnswerSelectionEvidence, useLearningAttemptEvidence, useLearningCloseSession, useLearningDownloadCertificate, useLearningEnroll, useLearningFinishAttempt, useLearningHistoricalSelectedPages, useLearningIssueCertificate, useLearningListAttemptHistory, useLearningListScoreHistory, useLearningOpenLesson, useLearningOpenPathStep, useLearningPageEvidence, useLearningPageEvidenceDetail, useLearningPathIntroduction, useLearningRateExercisePage, useLearningReadAttempt, useLearningReadAttemptResource, useLearningReadCertificate, useLearningReadCourse, useLearningReadEnrollmentHistory, useLearningReadPathProgress, useLearningReadVocabulary, useLearningRecordActivity, useLearningReserveCourseUpload, useLearningReserveExerciseUpload, useLearningStartAttempt, useLearningStartSession, useLearningUpdateProgress, useLearningUpdateVocabulary, useLearningUpgradeCourseEdition, useLearningUploadBytes, useLearningVocabularyResource };
1666
+
1667
+ //# sourceMappingURL=biblio-learning.js.map