musora-content-services 2.167.0 → 2.167.2

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 (342) hide show
  1. package/.agent/decisions/2026-04-28-tma-275-mcs-sanity-add-a-v2-url-segmen.md +0 -0
  2. package/.agent/decisions/2026-05-19-content-progress-ts-part-2.md +0 -0
  3. package/.agent/decisions/2026-05-20-live-event-fetch-permissions-id.md +0 -0
  4. package/.agent/decisions/2026-07-17-onboarding-statuses.md +21 -0
  5. package/.claude/settings.local.json +48 -19
  6. package/.coderabbit.yaml +0 -0
  7. package/.editorconfig +0 -0
  8. package/.github/pull_request_template.md +0 -0
  9. package/.github/workflows/automated-testing.yml +0 -0
  10. package/.github/workflows/conventional-commits.yaml +0 -0
  11. package/.github/workflows/docs.js.yml +0 -0
  12. package/.prettierignore +0 -0
  13. package/.prettierrc +0 -0
  14. package/CHANGELOG.md +14 -0
  15. package/CLAUDE.md +0 -0
  16. package/README.md +0 -0
  17. package/babel.config.cjs +0 -0
  18. package/codecov.yml +0 -0
  19. package/jest.config.js +0 -0
  20. package/jest.integration.config.js +0 -0
  21. package/jest.live.config.js +0 -0
  22. package/jsdoc.json +0 -0
  23. package/package.json +1 -1
  24. package/src/constants/membership-permissions.ts +0 -0
  25. package/src/contentMetaData.js +0 -0
  26. package/src/contentTypeConfig.js +1 -0
  27. package/src/filterBuilder.js +0 -0
  28. package/src/index.d.ts +2 -0
  29. package/src/index.js +2 -0
  30. package/src/infrastructure/http/HttpClient.ts +0 -0
  31. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  32. package/src/infrastructure/http/index.ts +0 -0
  33. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  34. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  35. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  36. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  37. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  38. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  39. package/src/infrastructure/sanity/README.md +0 -0
  40. package/src/infrastructure/sanity/SanityClient.ts +0 -0
  41. package/src/infrastructure/sanity/clients/ContentClient.ts +0 -0
  42. package/src/infrastructure/sanity/examples/usage.ts +0 -0
  43. package/src/infrastructure/sanity/executors/FetchQueryExecutor.ts +0 -0
  44. package/src/infrastructure/sanity/index.ts +0 -0
  45. package/src/infrastructure/sanity/interfaces/ConfigProvider.ts +0 -0
  46. package/src/infrastructure/sanity/interfaces/FetchByIdOptions.ts +0 -0
  47. package/src/infrastructure/sanity/interfaces/QueryExecutor.ts +0 -0
  48. package/src/infrastructure/sanity/interfaces/SanityConfig.ts +0 -0
  49. package/src/infrastructure/sanity/interfaces/SanityError.ts +0 -0
  50. package/src/infrastructure/sanity/interfaces/SanityQuery.ts +0 -0
  51. package/src/infrastructure/sanity/interfaces/SanityResponse.ts +0 -0
  52. package/src/infrastructure/sanity/providers/DefaultConfigProvider.ts +0 -0
  53. package/src/lib/ads/monoid.ts +0 -0
  54. package/src/lib/ads/semigroup.ts +0 -0
  55. package/src/lib/brands.ts +0 -0
  56. package/src/lib/lastUpdated.js +0 -0
  57. package/src/lib/sanity/decorators/base.ts +0 -0
  58. package/src/lib/sanity/decorators/examples.ts +0 -0
  59. package/src/lib/sanity/decorators/navigate-to.ts +0 -0
  60. package/src/lib/sanity/decorators/need-access.ts +0 -0
  61. package/src/lib/sanity/decorators/need-lifetime-upgrade.ts +0 -0
  62. package/src/lib/sanity/decorators/page-type.ts +0 -0
  63. package/src/lib/sanity/field-access.ts +0 -0
  64. package/src/lib/sanity/filter.ts +0 -0
  65. package/src/lib/sanity/query.ts +0 -0
  66. package/src/services/api/types.js +0 -0
  67. package/src/services/api/types.ts +0 -0
  68. package/src/services/awards/award-callbacks.js +0 -0
  69. package/src/services/awards/award-query.js +0 -0
  70. package/src/services/awards/internal/.indexignore +0 -0
  71. package/src/services/awards/internal/award-definitions.js +0 -0
  72. package/src/services/awards/internal/award-events.js +0 -0
  73. package/src/services/awards/internal/award-manager.js +0 -0
  74. package/src/services/awards/internal/certificate-builder.js +0 -0
  75. package/src/services/awards/internal/completion-data-generator.js +0 -0
  76. package/src/services/awards/internal/content-progress-observer.js +0 -0
  77. package/src/services/awards/internal/image-utils.js +0 -0
  78. package/src/services/awards/internal/message-generator.js +0 -0
  79. package/src/services/awards/internal/types.js +0 -0
  80. package/src/services/awards/types.d.ts +0 -0
  81. package/src/services/awards/types.js +0 -0
  82. package/src/services/config.js +0 -0
  83. package/src/services/content/artist.ts +0 -0
  84. package/src/services/content/content.ts +0 -0
  85. package/src/services/content/genre.ts +0 -0
  86. package/src/services/content/instructor.ts +0 -0
  87. package/src/services/content-org/content-org.js +0 -0
  88. package/src/services/content-org/guided-courses.ts +0 -0
  89. package/src/services/content-org/learning-paths.ts +0 -0
  90. package/src/services/content-org/playlists-types.js +0 -0
  91. package/src/services/content-org/playlists.js +0 -0
  92. package/src/services/content.js +0 -0
  93. package/src/services/contentAggregator.js +0 -0
  94. package/src/services/contentLikes.js +0 -0
  95. package/src/services/contentProgress.js +1 -1
  96. package/src/services/dataContext.js +0 -0
  97. package/src/services/dateUtils.js +0 -0
  98. package/src/services/endScreen/README.md +0 -0
  99. package/src/services/endScreen/endScreen.ts +0 -0
  100. package/src/services/endScreen/types.ts +0 -0
  101. package/src/services/eventsAPI.js +49 -7
  102. package/src/services/forums/categories.ts +0 -0
  103. package/src/services/forums/forums.ts +0 -0
  104. package/src/services/forums/posts.ts +0 -0
  105. package/src/services/forums/threads.ts +0 -0
  106. package/src/services/gamification/awards.ts +0 -0
  107. package/src/services/gamification/gamification.js +0 -0
  108. package/src/services/imageSRCBuilder.js +0 -0
  109. package/src/services/imageSRCVerify.js +0 -0
  110. package/src/services/liveTesting.ts +0 -0
  111. package/src/services/multi-user-accounts/multi-user-accounts.ts +0 -0
  112. package/src/services/offline/activities.ts +0 -0
  113. package/src/services/offline/practices.ts +0 -0
  114. package/src/services/offline/progress.ts +0 -0
  115. package/src/services/permissions/PermissionsAdapter.ts +0 -0
  116. package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
  117. package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
  118. package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
  119. package/src/services/permissions/README.md +0 -0
  120. package/src/services/permissions/index.ts +0 -0
  121. package/src/services/permissions/permissions.ts +0 -0
  122. package/src/services/permissions/types.d.ts +0 -0
  123. package/src/services/progress/.indexignore +0 -0
  124. package/src/services/progress/collections.ts +0 -0
  125. package/src/services/progress/index.ts +0 -0
  126. package/src/services/progress/internal/bubble.ts +0 -0
  127. package/src/services/progress/internal/queries.ts +0 -0
  128. package/src/services/progress/state.ts +0 -0
  129. package/src/services/progress/types.ts +0 -0
  130. package/src/services/progress/utils.ts +0 -0
  131. package/src/services/progress-events.js +0 -0
  132. package/src/services/progress-row/base.js +0 -0
  133. package/src/services/progress-row/rows/.indexignore +0 -0
  134. package/src/services/progress-row/rows/content-card.js +0 -0
  135. package/src/services/progress-row/rows/method-card.js +0 -0
  136. package/src/services/progress-row/rows/playlist-card.js +0 -0
  137. package/src/services/railcontent.js +0 -0
  138. package/src/services/recommendations.js +0 -0
  139. package/src/services/reporting/README.md +0 -0
  140. package/src/services/reporting/reporting.ts +0 -0
  141. package/src/services/reporting/types.ts +0 -0
  142. package/src/services/search.ts +0 -0
  143. package/src/services/sentry/.indexignore +0 -0
  144. package/src/services/sentry/index.ts +0 -0
  145. package/src/services/state.ts +0 -0
  146. package/src/services/sync/.indexignore +0 -0
  147. package/src/services/sync/adapters/factory.ts +0 -0
  148. package/src/services/sync/adapters/lokijs.ts +0 -0
  149. package/src/services/sync/adapters/sqlite.ts +0 -0
  150. package/src/services/sync/context/index.ts +0 -0
  151. package/src/services/sync/context/providers/base.ts +0 -0
  152. package/src/services/sync/context/providers/connectivity.ts +0 -0
  153. package/src/services/sync/context/providers/durability.ts +0 -0
  154. package/src/services/sync/context/providers/index.ts +0 -0
  155. package/src/services/sync/context/providers/session.ts +0 -0
  156. package/src/services/sync/context/providers/tabs.ts +0 -0
  157. package/src/services/sync/context/providers/visibility.ts +0 -0
  158. package/src/services/sync/database/factory.ts +0 -0
  159. package/src/services/sync/debug.ts +0 -0
  160. package/src/services/sync/effects/index.ts +0 -0
  161. package/src/services/sync/effects/logout-warning.ts +0 -0
  162. package/src/services/sync/effects/push-failure-notification.ts +0 -0
  163. package/src/services/sync/errors/boundary.ts +0 -0
  164. package/src/services/sync/errors/index.ts +0 -0
  165. package/src/services/sync/errors/validators.ts +0 -0
  166. package/src/services/sync/fetch.ts +0 -0
  167. package/src/services/sync/index.ts +0 -0
  168. package/src/services/sync/manager.ts +0 -0
  169. package/src/services/sync/models/Base.ts +0 -0
  170. package/src/services/sync/models/ContentLike.ts +0 -0
  171. package/src/services/sync/models/ContentProgress.ts +0 -0
  172. package/src/services/sync/models/Practice.ts +0 -0
  173. package/src/services/sync/models/PracticeDayNote.ts +0 -0
  174. package/src/services/sync/models/UserAwardProgress.ts +0 -0
  175. package/src/services/sync/models/index.ts +0 -0
  176. package/src/services/sync/repositories/base.ts +0 -0
  177. package/src/services/sync/repositories/content-likes.ts +0 -0
  178. package/src/services/sync/repositories/content-progress.ts +0 -0
  179. package/src/services/sync/repositories/index.ts +0 -0
  180. package/src/services/sync/repositories/practice-day-notes.ts +0 -0
  181. package/src/services/sync/repositories/practices.ts +0 -0
  182. package/src/services/sync/repositories/user-award-progress.ts +0 -0
  183. package/src/services/sync/repository-proxy.ts +0 -0
  184. package/src/services/sync/resolver.ts +0 -0
  185. package/src/services/sync/retry.ts +0 -0
  186. package/src/services/sync/run-scope.ts +0 -0
  187. package/src/services/sync/schema/index.ts +0 -0
  188. package/src/services/sync/serializers/index.ts +0 -0
  189. package/src/services/sync/serializers/model.ts +0 -0
  190. package/src/services/sync/serializers/raw.ts +0 -0
  191. package/src/services/sync/stale-record-cleanup.ts +0 -0
  192. package/src/services/sync/store/index.ts +0 -0
  193. package/src/services/sync/store/push-coalescer.ts +0 -0
  194. package/src/services/sync/store-configs.ts +0 -0
  195. package/src/services/sync/strategies/base.ts +0 -0
  196. package/src/services/sync/strategies/index.ts +0 -0
  197. package/src/services/sync/strategies/initial.ts +0 -0
  198. package/src/services/sync/strategies/polling.ts +0 -0
  199. package/src/services/sync/telemetry/flood-prevention.ts +0 -0
  200. package/src/services/sync/telemetry/index.ts +0 -0
  201. package/src/services/sync/telemetry/sampling.ts +0 -0
  202. package/src/services/sync/utils/event-emitter.ts +0 -0
  203. package/src/services/sync/utils/index.ts +0 -0
  204. package/src/services/sync/utils/throttle.ts +0 -0
  205. package/src/services/sync/utils/timers.ts +0 -0
  206. package/src/services/types.js +0 -0
  207. package/src/services/urlBuilder.ts +0 -0
  208. package/src/services/user/account.ts +12 -2
  209. package/src/services/user/chat.js +0 -0
  210. package/src/services/user/interests.js +0 -0
  211. package/src/services/user/management.js +0 -0
  212. package/src/services/user/notifications.js +0 -0
  213. package/src/services/user/onboarding.ts +22 -0
  214. package/src/services/user/payments.ts +0 -0
  215. package/src/services/user/playerSettings.ts +0 -0
  216. package/src/services/user/profile.ts +0 -0
  217. package/src/services/user/sessions.js +0 -0
  218. package/src/services/user/streakCalculator.ts +0 -0
  219. package/src/services/user/types.js +0 -0
  220. package/src/services/user/user-management-system.js +0 -0
  221. package/src/services/userActivity.js +0 -0
  222. package/src/services/whoLiked.ts +0 -0
  223. package/test/initializeTests.js +0 -0
  224. package/test/integration/awards/award-exclusion-handling.test.ts +0 -0
  225. package/test/integration/awards/internal/image-utils.test.ts +0 -0
  226. package/test/integration/content-progress/__mocks__/mocks.ts +0 -0
  227. package/test/integration/content-progress/contentProgress.test.ts +0 -0
  228. package/test/integration/content-progress/e2eOfflineProgress.test.ts +0 -0
  229. package/test/integration/content-progress/e2eProgress.test.ts +0 -0
  230. package/test/integration/content-progress/getters.test.ts +0 -0
  231. package/test/integration/content-progress/helpers.test.ts +0 -0
  232. package/test/integration/content-progress/offlineContentProgress.test.ts +0 -0
  233. package/test/integration/forums.test.ts +0 -0
  234. package/test/integration/infrastructure/FetchRequestExecutor.test.ts +0 -0
  235. package/test/integration/initializeTestDB.ts +0 -0
  236. package/test/integration/learning-paths.test.ts +0 -0
  237. package/test/integration/notifications.test.ts +0 -0
  238. package/test/integration/progress-row/content-card.test.ts +0 -0
  239. package/test/integration/sync/adapters/idb-errors.test.ts +0 -0
  240. package/test/integration/sync/adapters/sqlite-errors.test.ts +0 -0
  241. package/test/integration/sync/fetch.test.ts +0 -0
  242. package/test/integration/sync/repositories/content-likes.test.ts +0 -0
  243. package/test/integration/sync/repositories/practices.test.ts +0 -0
  244. package/test/integration/sync/repositories/progress.test.ts +0 -0
  245. package/test/integration/sync/repositories/user-award-progress.static.test.ts +0 -0
  246. package/test/integration/sync/repositories/user-award-progress.test.ts +0 -0
  247. package/test/integration/sync/store/cross-user-protection.test.ts +0 -0
  248. package/test/integration/sync/store/store-idb.test.ts +0 -0
  249. package/test/integration/sync/store/store.test.ts +0 -0
  250. package/test/integration/user/permissions.test.js +0 -0
  251. package/test/integration/userActivity.test.ts +0 -0
  252. package/test/live/README.md +0 -0
  253. package/test/live/content.test.js +0 -0
  254. package/test/localStorageMock.js +0 -0
  255. package/test/log.js +0 -0
  256. package/test/mockData/award-definitions.js +0 -0
  257. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  258. package/test/mockData/mockData_progress_content.json +0 -0
  259. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  260. package/test/mockData/mockData_user_practices.json +0 -0
  261. package/test/setupConsole.js +0 -0
  262. package/test/setupNetworkGuard.js +0 -0
  263. package/test/setupTimers.js +0 -0
  264. package/test/unit/HttpClient.test.ts +0 -0
  265. package/test/unit/awards/award-alacarte-observer.test.ts +0 -0
  266. package/test/unit/awards/award-auto-refresh.test.ts +0 -0
  267. package/test/unit/awards/award-calculations.test.ts +0 -0
  268. package/test/unit/awards/award-callbacks.test.ts +0 -0
  269. package/test/unit/awards/award-certificate-display.test.ts +0 -0
  270. package/test/unit/awards/award-collection-edge-cases.test.ts +0 -0
  271. package/test/unit/awards/award-collection-filtering.test.ts +0 -0
  272. package/test/unit/awards/award-completion-flow.test.ts +0 -0
  273. package/test/unit/awards/award-multi-lesson.test.ts +0 -0
  274. package/test/unit/awards/award-observer-integration.test.ts +0 -0
  275. package/test/unit/awards/award-query-messages.test.ts +0 -0
  276. package/test/unit/awards/award-user-collection.test.ts +0 -0
  277. package/test/unit/awards/duplicate-prevention.test.ts +0 -0
  278. package/test/unit/awards/helpers/completion-mock.ts +0 -0
  279. package/test/unit/awards/helpers/index.ts +0 -0
  280. package/test/unit/awards/helpers/mock-setup.ts +0 -0
  281. package/test/unit/awards/helpers/progress-emitter.ts +0 -0
  282. package/test/unit/awards/message-generator.test.ts +0 -0
  283. package/test/unit/content-progress/bubbleTrickle.test.ts +0 -0
  284. package/test/unit/content-progress/helpers.test.ts +0 -0
  285. package/test/unit/content-progress/navigateTo.test.ts +11 -0
  286. package/test/unit/contentLikes.test.ts +0 -0
  287. package/test/unit/contentMetaData.test.ts +0 -0
  288. package/test/unit/dataContext.test.ts +0 -0
  289. package/test/unit/dateUtils.test.ts +0 -0
  290. package/test/unit/endScreen.test.js +0 -0
  291. package/test/unit/eventsAPI.test.ts +159 -0
  292. package/test/unit/imageSRCBuilder.test.ts +0 -0
  293. package/test/unit/imageSRCVerify.test.ts +0 -0
  294. package/test/unit/infrastructure/DefaultHeaderProvider.test.ts +0 -0
  295. package/test/unit/infrastructure/sanity/ContentClient.test.ts +0 -0
  296. package/test/unit/infrastructure/sanity/DefaultConfigProvider.test.ts +0 -0
  297. package/test/unit/infrastructure/sanity/FetchQueryExecutor.test.ts +0 -0
  298. package/test/unit/infrastructure/sanity/SanityClient.test.ts +0 -0
  299. package/test/unit/lib/__snapshots__/filter.test.ts.snap +0 -0
  300. package/test/unit/lib/filter.test.ts +0 -0
  301. package/test/unit/lib/lastUpdated.test.ts +0 -0
  302. package/test/unit/lib/query.test.ts +0 -0
  303. package/test/unit/lib/sanity/decorators/base.test.ts +0 -0
  304. package/test/unit/lib/sanity/decorators/navigate-to.test.ts +0 -0
  305. package/test/unit/lib/sanity/decorators/need-access.test.ts +0 -0
  306. package/test/unit/lib/sanity/decorators/need-lifetime-upgrade.test.ts +0 -0
  307. package/test/unit/lib/sanity/decorators/page-type.test.ts +0 -0
  308. package/test/unit/playerSettings.test.ts +0 -0
  309. package/test/unit/progress-row/content-card.test.ts +0 -0
  310. package/test/unit/progress-row/playlist-card.test.ts +0 -0
  311. package/test/unit/progressRows.test.ts +0 -0
  312. package/test/unit/recommendations.test.js +0 -0
  313. package/test/unit/sanityQueryService.test.ts +0 -0
  314. package/test/unit/search.test.ts +0 -0
  315. package/test/unit/sentry.test.ts +0 -0
  316. package/test/unit/services/progress-internal/bubble.test.ts +0 -0
  317. package/test/unit/services/progress.test.ts +0 -0
  318. package/test/unit/streakMessage.test.ts +0 -0
  319. package/test/unit/sync/context.test.ts +0 -0
  320. package/test/unit/sync/effects/logout-warning.test.ts +0 -0
  321. package/test/unit/sync/effects/push-failure-notification.test.ts +0 -0
  322. package/test/unit/sync/errors/sync-errors.test.ts +0 -0
  323. package/test/unit/sync/errors/validators.test.ts +0 -0
  324. package/test/unit/sync/helpers/TestModel.ts +0 -0
  325. package/test/unit/sync/helpers/index.ts +0 -0
  326. package/test/unit/sync/manager.test.ts +0 -0
  327. package/test/unit/sync/models/user-award-progress.test.ts +0 -0
  328. package/test/unit/sync/resolver.test.ts +0 -0
  329. package/test/unit/sync/retry.test.ts +0 -0
  330. package/test/unit/sync/run-scope.test.ts +0 -0
  331. package/test/unit/sync/stale-record-cleanup.test.ts +0 -0
  332. package/test/unit/sync/store/push-coalescer.test.ts +0 -0
  333. package/test/unit/sync/store-configs.test.ts +0 -0
  334. package/test/unit/sync/telemetry/sync-telemetry.test.ts +0 -0
  335. package/test/unit/sync/utils/event-emitter.test.ts +0 -0
  336. package/test/unit/sync/utils/throttle.test.ts +0 -0
  337. package/test/unit/url-builder.test.ts +0 -0
  338. package/test/unit/user/account.test.ts +14 -3
  339. package/test/unit/user/permissions.test.js +0 -0
  340. package/tools/generate-index.cjs +0 -0
  341. package/tsconfig.json +0 -0
  342. package/usage/sanity/decorators/examples.ts +0 -0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -22,17 +22,27 @@ export async function status(email: string): Promise<{ requires_setup: boolean }
22
22
  )
23
23
  }
24
24
 
25
+ export interface SendAccountSetupEmailOptions {
26
+ has_skipped_paywall?: boolean
27
+ [key: string]: any
28
+ }
29
+
25
30
  /**
26
- * @param {string} email - The email address to send the account setup email to.
31
+ * @param {Send} email - The email address to send the account setup email to.
27
32
  * @returns {Promise<void>} - A promise that resolves when the email is sent or an HttpError if the request fails.
28
33
  * @throws {HttpError} - Throws HttpError if the request fails.
29
34
  */
30
- export async function sendAccountSetupEmail(email: string, token?: string): Promise<void> {
35
+ export async function sendAccountSetupEmail(
36
+ email: string,
37
+ token?: string,
38
+ options: SendAccountSetupEmailOptions = { has_skipped_paywall: false }
39
+ ): Promise<void> {
31
40
  const httpClient = new HttpClient(globalConfig.baseUrl)
32
41
  return httpClient.post<void>(
33
42
  `/api/user-management-system/v1/accounts/${encodeURIComponent(email)}/send-setup-email`,
34
43
  {
35
44
  token,
45
+ ...options,
36
46
  }
37
47
  )
38
48
  }
File without changes
File without changes
File without changes
File without changes
@@ -117,6 +117,28 @@ export async function userOnboardingForBrand(brand: string): Promise<Onboarding>
117
117
  )
118
118
  }
119
119
 
120
+ export interface OnboardingBrandStatus {
121
+ brand: string
122
+ is_completed: boolean
123
+ completed_flow: string | null
124
+ completed_at: Date | null
125
+ }
126
+
127
+ export interface OnboardingStatus {
128
+ has_completed_onboarding: boolean
129
+ brands: OnboardingBrandStatus[]
130
+ }
131
+
132
+ /**
133
+ * Fetches the current user's onboarding completion status across all brands.
134
+ *
135
+ * @returns {Promise<OnboardingStatus>} - A promise that resolves with the cross-brand onboarding status.
136
+ * @throws {HttpError} - If the HTTP request fails.
137
+ */
138
+ export async function getOnboardingStatus(): Promise<OnboardingStatus> {
139
+ return GET(`/api/user-management-system/v1/users/${globalConfig.sessionConfig.userId}/onboardings/status`)
140
+ }
141
+
120
142
  export interface OnboardingRecommendedContent {
121
143
  id: number
122
144
  title: string
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/test/log.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -254,6 +254,17 @@ describe('getNavigateTo', () => {
254
254
  expect(result[1]).toMatchObject({ id: 101 })
255
255
  })
256
256
 
257
+ test('documentary started lastInteracted started navigates to lastInteracted child', async () => {
258
+ mockProgressRecords = [
259
+ { content_id: 1, state: 'started', progress_percent: 50, updated_at: 1000 },
260
+ { content_id: 101, state: 'started', progress_percent: 100, updated_at: 900 },
261
+ { content_id: 102, state: 'started', progress_percent: 30, updated_at: 1000 },
262
+ ]
263
+ mockLastInteracted = 101
264
+ const result = await getNavigateTo([{ id: 1, type: 'documentary', children: [child(101), child(102)] }])
265
+ expect(result[1]).toMatchObject({ id: 101 })
266
+ })
267
+
257
268
  test('course started lastInteracted completed navigates to first incomplete after lastInteracted', async () => {
258
269
  mockProgressRecords = [
259
270
  { content_id: 1, state: 'started', progress_percent: 60, updated_at: 1000 },
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,159 @@
1
+ import eventsAPISingleton from '../../src/services/eventsAPI.js'
2
+ import { initializeTestService } from '../initializeTests.js'
3
+
4
+ const notificationsModule = require('../../src/services/user/notifications.js')
5
+ const EventsAPI = eventsAPISingleton.constructor as new () => typeof eventsAPISingleton
6
+
7
+ function deferred<T>() {
8
+ let resolve!: (value: T) => void
9
+ const promise = new Promise<T>((res) => {
10
+ resolve = res
11
+ })
12
+
13
+ return { promise, resolve }
14
+ }
15
+
16
+ describe('EventsAPI notification polling lifecycle', () => {
17
+ let api: typeof eventsAPISingleton
18
+ let fetchUnreadCountMock: jest.SpyInstance
19
+
20
+ beforeEach(() => {
21
+ initializeTestService()
22
+ jest.useFakeTimers()
23
+
24
+ api = new EventsAPI()
25
+ jest.spyOn(api, 'initPollingControl').mockResolvedValue({})
26
+ fetchUnreadCountMock = jest
27
+ .spyOn(notificationsModule, 'fetchUnreadCount')
28
+ .mockResolvedValue({ data: 0 })
29
+ })
30
+
31
+ afterEach(() => {
32
+ api.destroy()
33
+ jest.useRealTimers()
34
+ jest.restoreAllMocks()
35
+ })
36
+
37
+ test('initialize keeps the existing polling behavior', async () => {
38
+ await api.initialize({ brand: 'pianote' })
39
+
40
+ expect(fetchUnreadCountMock).toHaveBeenCalledWith({ brand: 'pianote' })
41
+ expect(api.pollingInterval).not.toBeNull()
42
+
43
+ fetchUnreadCountMock.mockClear()
44
+ await jest.advanceTimersByTimeAsync(60000)
45
+
46
+ expect(fetchUnreadCountMock).toHaveBeenCalledTimes(1)
47
+ })
48
+
49
+ test('pause stops polling without removing subscribers', async () => {
50
+ const handler = jest.fn()
51
+ api.addNotificationStateUpdatedHandler(handler)
52
+ await api.initialize()
53
+ handler.mockClear()
54
+ fetchUnreadCountMock.mockClear()
55
+
56
+ api.pauseNotificationPolling()
57
+ await jest.advanceTimersByTimeAsync(120000)
58
+
59
+ expect(api.pollingInterval).toBeNull()
60
+ expect(api.onNotificationStateUpdated).toEqual([handler])
61
+ expect(fetchUnreadCountMock).not.toHaveBeenCalled()
62
+ })
63
+
64
+ test('resume starts one interval and immediately refreshes existing subscribers', async () => {
65
+ const handler = jest.fn()
66
+ api.addNotificationStateUpdatedHandler(handler)
67
+ await api.initialize()
68
+ api.pauseNotificationPolling()
69
+ fetchUnreadCountMock.mockResolvedValue({ data: 1, liveEvent: null })
70
+ fetchUnreadCountMock.mockClear()
71
+ handler.mockClear()
72
+
73
+ await api.resumeNotificationPolling()
74
+ const resumedInterval = api.pollingInterval
75
+ await api.resumeNotificationPolling()
76
+
77
+ expect(resumedInterval).not.toBeNull()
78
+ expect(api.pollingInterval).toBe(resumedInterval)
79
+ expect(fetchUnreadCountMock).toHaveBeenCalledTimes(2)
80
+ expect(handler).toHaveBeenLastCalledWith({ unreadCount: 1, liveEvent: null })
81
+ })
82
+
83
+ test('repeated pause calls are safe', async () => {
84
+ await api.initialize()
85
+
86
+ api.pauseNotificationPolling()
87
+ api.pauseNotificationPolling()
88
+
89
+ expect(api.pollingInterval).toBeNull()
90
+ })
91
+
92
+ test('pause during asynchronous setup prevents the interval from being created', async () => {
93
+ const pollingControl = deferred<Record<string, never>>()
94
+ jest.spyOn(api, 'initPollingControl').mockReturnValue(pollingControl.promise)
95
+
96
+ const initializePromise = api.initialize()
97
+ api.pauseNotificationPolling()
98
+ pollingControl.resolve({})
99
+ await initializePromise
100
+
101
+ expect(api.pollingInterval).toBeNull()
102
+ expect(fetchUnreadCountMock).toHaveBeenCalledTimes(1)
103
+ })
104
+
105
+ test('resume during asynchronous setup creates no duplicate interval', async () => {
106
+ const pollingControl = deferred<Record<string, never>>()
107
+ jest.spyOn(api, 'initPollingControl').mockReturnValue(pollingControl.promise)
108
+
109
+ const initializePromise = api.initialize()
110
+ api.pauseNotificationPolling()
111
+ const resumePromise = api.resumeNotificationPolling()
112
+ const resumedInterval = api.pollingInterval
113
+ pollingControl.resolve({})
114
+ await Promise.all([initializePromise, resumePromise])
115
+
116
+ expect(resumedInterval).not.toBeNull()
117
+ expect(api.pollingInterval).toBe(resumedInterval)
118
+ })
119
+
120
+ test('pause and resume while the initial unread request is pending restores polling', async () => {
121
+ const initialUnreadCount = deferred<{ data: number }>()
122
+ fetchUnreadCountMock
123
+ .mockReturnValueOnce(initialUnreadCount.promise)
124
+ .mockResolvedValue({ data: 1 })
125
+
126
+ const initializePromise = api.initialize()
127
+ await Promise.resolve()
128
+ await Promise.resolve()
129
+ expect(api.pollingInterval).not.toBeNull()
130
+
131
+ api.pauseNotificationPolling()
132
+ const resumePromise = api.resumeNotificationPolling()
133
+
134
+ expect(api.pollingInterval).not.toBeNull()
135
+ initialUnreadCount.resolve({ data: 0 })
136
+ await Promise.all([initializePromise, resumePromise])
137
+
138
+ fetchUnreadCountMock.mockClear()
139
+ await jest.advanceTimersByTimeAsync(60000)
140
+ expect(fetchUnreadCountMock).toHaveBeenCalledTimes(1)
141
+ })
142
+
143
+ test('destroy remains a full teardown and initialize can start again', async () => {
144
+ api.addNotificationStateUpdatedHandler(jest.fn())
145
+ await api.initialize()
146
+
147
+ api.destroy()
148
+
149
+ expect(api.pollingInterval).toBeNull()
150
+ expect(api.onNotificationStateUpdated).toEqual([])
151
+ expect(api.isLiveEventPollingActive).toBe(false)
152
+
153
+ fetchUnreadCountMock.mockClear()
154
+ await api.initialize()
155
+
156
+ expect(api.pollingInterval).not.toBeNull()
157
+ expect(fetchUnreadCountMock).toHaveBeenCalledTimes(1)
158
+ })
159
+ })
File without changes
File without changes