musora-content-services 2.85.1 → 2.86.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 (222) hide show
  1. package/.coderabbit.yaml +0 -0
  2. package/.editorconfig +0 -0
  3. package/.github/pull_request_template.md +0 -0
  4. package/.github/workflows/conventional-commits.yaml +0 -0
  5. package/.github/workflows/docs.js.yml +0 -0
  6. package/.github/workflows/node.js.yml +0 -0
  7. package/.prettierignore +0 -0
  8. package/.prettierrc +0 -0
  9. package/CHANGELOG.md +19 -0
  10. package/README.md +0 -0
  11. package/babel.config.cjs +0 -0
  12. package/docs/Content.html +0 -0
  13. package/docs/ContentOrganization.html +2 -2
  14. package/docs/Forums.html +2 -2
  15. package/docs/Gamification.html +2 -2
  16. package/docs/TestUser.html +2 -2
  17. package/docs/UserManagementSystem.html +2 -2
  18. package/docs/api_types.js.html +2 -2
  19. package/docs/config.js.html +5 -2
  20. package/docs/content-org_content-org.js.html +2 -2
  21. package/docs/content-org_guided-courses.ts.html +2 -2
  22. package/docs/content-org_learning-paths.ts.html +126 -24
  23. package/docs/content-org_playlists-types.js.html +2 -2
  24. package/docs/content-org_playlists.js.html +2 -2
  25. package/docs/content.js.html +88 -10
  26. package/docs/content_artist.ts.html +36 -41
  27. package/docs/content_content.ts.html +0 -0
  28. package/docs/content_genre.ts.html +29 -34
  29. package/docs/content_instructor.ts.html +25 -27
  30. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  31. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  32. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  33. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  34. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  35. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  36. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  37. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  38. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  39. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  40. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  41. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  42. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  43. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  44. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  45. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  46. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  47. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  48. package/docs/forums_categories.ts.html +22 -3
  49. package/docs/forums_discussions.js.html +0 -0
  50. package/docs/forums_forum.js.html +0 -0
  51. package/docs/forums_forums.ts.html +2 -2
  52. package/docs/forums_posts.ts.html +2 -2
  53. package/docs/forums_threads.ts.html +9 -9
  54. package/docs/gamification_awards.js.html +0 -0
  55. package/docs/gamification_awards.ts.html +26 -12
  56. package/docs/gamification_gamification.js.html +2 -2
  57. package/docs/gamification_types.js.html +0 -0
  58. package/docs/global.html +2 -2
  59. package/docs/index.html +2 -2
  60. package/docs/liveTesting.ts.html +2 -2
  61. package/docs/module-Accounts.html +14 -14
  62. package/docs/module-Artist.html +12 -10
  63. package/docs/module-Awards.html +106 -6
  64. package/docs/module-Categories.html +0 -0
  65. package/docs/module-Config.html +5 -4
  66. package/docs/module-Content-Services-V2.html +440 -9
  67. package/docs/module-ForumCategories.html +0 -0
  68. package/docs/module-ForumDiscussions.html +0 -0
  69. package/docs/module-Forums.html +627 -63
  70. package/docs/module-Genre.html +6 -6
  71. package/docs/module-GuidedCourses.html +2 -2
  72. package/docs/module-Instructor.html +10 -10
  73. package/docs/module-Interests.html +2 -2
  74. package/docs/module-LearningPaths.html +640 -12
  75. package/docs/module-Onboarding.html +32 -8
  76. package/docs/module-Payments.html +2 -2
  77. package/docs/module-Permissions.html +2 -2
  78. package/docs/module-Playlists.html +2 -2
  79. package/docs/module-ProgressRow.html +2 -2
  80. package/docs/module-Railcontent-Services.html +2 -2
  81. package/docs/module-Sanity-Services.html +786 -1853
  82. package/docs/module-Sessions.html +2 -2
  83. package/docs/module-Threads.html +0 -0
  84. package/docs/module-UserActivity.html +4 -4
  85. package/docs/module-UserChat.html +2 -2
  86. package/docs/module-UserManagement.html +2 -2
  87. package/docs/module-UserMemberships.html +2 -2
  88. package/docs/module-UserNotifications.html +2 -2
  89. package/docs/module-UserProfile.html +2 -2
  90. package/docs/progress-row_method-card.js.html +3 -3
  91. package/docs/railcontent.js.html +2 -2
  92. package/docs/sanity.js.html +230 -321
  93. package/docs/scripts/collapse.js +0 -0
  94. package/docs/scripts/commonNav.js +0 -0
  95. package/docs/scripts/linenumber.js +0 -0
  96. package/docs/scripts/nav.js +0 -0
  97. package/docs/scripts/polyfill.js +0 -0
  98. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  99. package/docs/scripts/prettify/lang-css.js +0 -0
  100. package/docs/scripts/prettify/prettify.js +0 -0
  101. package/docs/scripts/search.js +0 -0
  102. package/docs/styles/jsdoc.css +0 -0
  103. package/docs/styles/prettify.css +0 -0
  104. package/docs/userActivity.js.html +4 -3
  105. package/docs/user_account.ts.html +14 -13
  106. package/docs/user_chat.js.html +2 -2
  107. package/docs/user_interests.js.html +2 -2
  108. package/docs/user_management.js.html +2 -2
  109. package/docs/user_memberships.js.html +0 -0
  110. package/docs/user_memberships.ts.html +2 -2
  111. package/docs/user_notifications.js.html +2 -2
  112. package/docs/user_onboarding.ts.html +95 -4
  113. package/docs/user_payments.ts.html +2 -2
  114. package/docs/user_permissions.js.html +3 -3
  115. package/docs/user_profile.js.html +2 -2
  116. package/docs/user_sessions.js.html +2 -2
  117. package/docs/user_types.js.html +2 -2
  118. package/docs/user_user-management-system.js.html +2 -2
  119. package/jest.config.js +0 -0
  120. package/jsdoc.json +0 -0
  121. package/package.json +1 -1
  122. package/src/contentMetaData.js +0 -0
  123. package/src/contentTypeConfig.js +24 -16
  124. package/src/filterBuilder.js +0 -0
  125. package/src/index.d.ts +0 -0
  126. package/src/index.js +0 -0
  127. package/src/infrastructure/http/HttpClient.ts +0 -0
  128. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  129. package/src/infrastructure/http/index.ts +0 -0
  130. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  131. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  132. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  133. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  134. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  135. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  136. package/src/lib/brands.ts +8 -0
  137. package/src/lib/httpHelper.js +0 -0
  138. package/src/lib/lastUpdated.js +0 -0
  139. package/src/lib/sanity/query.ts +30 -0
  140. package/src/services/api/types.js +0 -0
  141. package/src/services/api/types.ts +0 -0
  142. package/src/services/config.js +0 -0
  143. package/src/services/content/artist.ts +34 -39
  144. package/src/services/content/content.ts +7 -1
  145. package/src/services/content/genre.ts +27 -32
  146. package/src/services/content/instructor.ts +23 -25
  147. package/src/services/content-org/content-org.js +0 -0
  148. package/src/services/content-org/guided-courses.ts +0 -0
  149. package/src/services/content-org/learning-paths.ts +4 -4
  150. package/src/services/content-org/playlists-types.js +0 -0
  151. package/src/services/content-org/playlists.js +0 -0
  152. package/src/services/content.js +0 -0
  153. package/src/services/contentAggregator.js +5 -1
  154. package/src/services/contentLikes.js +0 -0
  155. package/src/services/contentProgress.js +6 -6
  156. package/src/services/dataContext.js +0 -0
  157. package/src/services/dateUtils.js +0 -0
  158. package/src/services/eventsAPI.js +0 -0
  159. package/src/services/forums/categories.ts +0 -0
  160. package/src/services/forums/forums.ts +0 -0
  161. package/src/services/forums/posts.ts +0 -0
  162. package/src/services/forums/threads.ts +0 -0
  163. package/src/services/forums/types.ts +0 -0
  164. package/src/services/gamification/awards.ts +0 -0
  165. package/src/services/gamification/gamification.js +0 -0
  166. package/src/services/imageSRCBuilder.js +0 -0
  167. package/src/services/imageSRCVerify.js +0 -0
  168. package/src/services/liveTesting.ts +0 -0
  169. package/src/services/permissions/PermissionsAdapter.ts +0 -0
  170. package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
  171. package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
  172. package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
  173. package/src/services/permissions/README.md +0 -0
  174. package/src/services/permissions/index.ts +0 -0
  175. package/src/services/progress-row/method-card.js +0 -0
  176. package/src/services/railcontent.js +0 -0
  177. package/src/services/recommendations.js +0 -0
  178. package/src/services/sanity.js +52 -45
  179. package/src/services/types.js +0 -0
  180. package/src/services/user/account.ts +0 -0
  181. package/src/services/user/chat.js +0 -0
  182. package/src/services/user/interests.js +0 -0
  183. package/src/services/user/management.js +0 -0
  184. package/src/services/user/memberships.ts +0 -0
  185. package/src/services/user/notifications.js +0 -0
  186. package/src/services/user/onboarding.ts +93 -2
  187. package/src/services/user/payments.ts +0 -0
  188. package/src/services/user/permissions.js +0 -0
  189. package/src/services/user/profile.js +0 -0
  190. package/src/services/user/sessions.js +0 -0
  191. package/src/services/user/types.d.ts +0 -0
  192. package/src/services/user/types.js +0 -0
  193. package/src/services/user/user-management-system.js +0 -0
  194. package/src/services/userActivity.js +1 -1
  195. package/test/HttpClient.test.js +0 -0
  196. package/test/content.test.js +0 -0
  197. package/test/contentLikes.test.js +0 -0
  198. package/test/contentProgress.test.js +0 -0
  199. package/test/dataContext.test.js +0 -0
  200. package/test/forum.test.js +0 -0
  201. package/test/imageSRCBuilder.test.js +0 -0
  202. package/test/imageSRCVerify.test.js +0 -0
  203. package/test/initializeTests.js +0 -0
  204. package/test/learningPaths.test.js +0 -0
  205. package/test/lib/lastUpdated.test.js +0 -0
  206. package/test/live/contentProgressLive.test.js +0 -0
  207. package/test/live/railcontentLive.test.js +0 -0
  208. package/test/localStorageMock.js +0 -0
  209. package/test/log.js +0 -0
  210. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  211. package/test/mockData/mockData_progress_content.json +0 -0
  212. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  213. package/test/mockData/mockData_user_practices.json +0 -0
  214. package/test/notifications.test.js +0 -0
  215. package/test/progressRows.test.js +0 -0
  216. package/test/sanityQueryService.test.js +0 -0
  217. package/test/streakMessage.test.js +0 -0
  218. package/test/user/permissions.test.js +0 -0
  219. package/test/userActivity.test.js +0 -0
  220. package/tools/generate-index.cjs +0 -0
  221. package/.claude/settings.local.json +0 -14
  222. package/.yarnrc.yml +0 -1
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Accounts.html">Accounts</a><ul class='methods'><li data-type='method'><a href="module-Accounts.html#~confirmEmailChange">confirmEmailChange</a></li><li data-type='method'><a href="module-Accounts.html#~deleteAccount">deleteAccount</a></li><li data-type='method'><a href="module-Accounts.html#~numberOfActiveUsers">numberOfActiveUsers</a></li><li data-type='method'><a href="module-Accounts.html#~requestEmailChange">requestEmailChange</a></li><li data-type='method'><a href="module-Accounts.html#~resetPassword">resetPassword</a></li><li data-type='method'><a href="module-Accounts.html#~sendAccountSetupEmail">sendAccountSetupEmail</a></li><li data-type='method'><a href="module-Accounts.html#~sendPasswordResetEmail">sendPasswordResetEmail</a></li><li data-type='method'><a href="module-Accounts.html#~setupAccount">setupAccount</a></li><li data-type='method'><a href="module-Accounts.html#~status">status</a></li><li data-type='method'><a href="module-Accounts.html#~toggleStudentView">toggleStudentView</a></li></ul></li><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#~fetchAwardsForUser">fetchAwardsForUser</a></li><li data-type='method'><a href="module-Awards.html#~fetchCertificate">fetchCertificate</a></li><li data-type='method'><a href="module-Awards.html#~getAwardDataForGuidedContent">getAwardDataForGuidedContent</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getLegacyMethods">getLegacyMethods</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Forums.html">Forums</a><ul class='methods'><li data-type='method'><a href="module-Forums.html#~createForumCategory">createForumCategory</a></li><li data-type='method'><a href="module-Forums.html#~createPost">createPost</a></li><li data-type='method'><a href="module-Forums.html#~createThread">createThread</a></li><li data-type='method'><a href="module-Forums.html#~deletePost">deletePost</a></li><li data-type='method'><a href="module-Forums.html#~deleteThread">deleteThread</a></li><li data-type='method'><a href="module-Forums.html#~fetchCommunityGuidelines">fetchCommunityGuidelines</a></li><li data-type='method'><a href="module-Forums.html#~fetchFollowedThreads">fetchFollowedThreads</a></li><li data-type='method'><a href="module-Forums.html#~fetchForumCategories">fetchForumCategories</a></li><li data-type='method'><a href="module-Forums.html#~fetchLatestThreads">fetchLatestThreads</a></li><li data-type='method'><a href="module-Forums.html#~fetchPosts">fetchPosts</a></li><li data-type='method'><a href="module-Forums.html#~fetchThreads">fetchThreads</a></li><li data-type='method'><a href="module-Forums.html#~followThread">followThread</a></li><li data-type='method'><a href="module-Forums.html#~jumpToPost">jumpToPost</a></li><li data-type='method'><a href="module-Forums.html#~likePost">likePost</a></li><li data-type='method'><a href="module-Forums.html#~lockThread">lockThread</a></li><li data-type='method'><a href="module-Forums.html#~markThreadAsRead">markThreadAsRead</a></li><li data-type='method'><a href="module-Forums.html#~pinThread">pinThread</a></li><li data-type='method'><a href="module-Forums.html#~search">search</a></li><li data-type='method'><a href="module-Forums.html#~unfollowThread">unfollowThread</a></li><li data-type='method'><a href="module-Forums.html#~unlikePost">unlikePost</a></li><li data-type='method'><a href="module-Forums.html#~unlockThread">unlockThread</a></li><li data-type='method'><a href="module-Forums.html#~unpinThread">unpinThread</a></li><li data-type='method'><a href="module-Forums.html#~updateForumCategory">updateForumCategory</a></li><li data-type='method'><a href="module-Forums.html#~updatePost">updatePost</a></li><li data-type='method'><a href="module-Forums.html#~updateThread">updateThread</a></li></ul></li><li></li><li></li><li><a href="module-GuidedCourses.html">GuidedCourses</a></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-LearningPaths.html">LearningPaths</a><ul class='methods'><li data-type='method'><a href="module-LearningPaths.html#~fetchLearningPathLessons">fetchLearningPathLessons</a></li><li data-type='method'><a href="module-LearningPaths.html#~getActivePath">getActivePath</a></li><li data-type='method'><a href="module-LearningPaths.html#~getDailySession">getDailySession</a></li><li data-type='method'><a href="module-LearningPaths.html#~getLearningPath">getLearningPath</a></li><li data-type='method'><a href="module-LearningPaths.html#~getLearningPathLessonsByIds">getLearningPathLessonsByIds</a></li><li data-type='method'><a href="module-LearningPaths.html#~resetAllLearningPaths">resetAllLearningPaths</a></li><li data-type='method'><a href="module-LearningPaths.html#~startLearningPath">startLearningPath</a></li><li data-type='method'><a href="module-LearningPaths.html#~updateActivePath">updateActivePath</a></li><li data-type='method'><a href="module-LearningPaths.html#~updateDailySession">updateDailySession</a></li></ul></li><li><a href="module-Onboarding.html">Onboarding</a><ul class='methods'><li data-type='method'><a href="module-Onboarding.html#~getOnboardingRecommendedContent">getOnboardingRecommendedContent</a></li><li data-type='method'><a href="module-Onboarding.html#~startOnboarding">startOnboarding</a></li><li data-type='method'><a href="module-Onboarding.html#~updateOnboarding">updateOnboarding</a></li><li data-type='method'><a href="module-Onboarding.html#~userOnboardingForBrand">userOnboardingForBrand</a></li></ul></li><li><a href="module-Payments.html">Payments</a><ul class='methods'><li data-type='method'><a href="module-Payments.html#~fetchCustomerPayments">fetchCustomerPayments</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.undeletePlaylist">undeletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~deleteItemsFromPlaylist">deleteItemsFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~restoreItemFromPlaylist">restoreItemFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-ProgressRow.html">ProgressRow</a></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComment">fetchComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentComplete">postContentComplete</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentReset">postContentReset</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentRestore">postContentRestore</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentStart">postContentStart</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.restoreComment">restoreComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchArtists">fetchArtists</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCoachLessons">fetchCoachLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2IntroVideo">fetchMethodV2IntroVideo</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2Structure">fetchMethodV2Structure</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2StructureFromId">fetchMethodV2StructureFromId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSiblingContent">fetchSiblingContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-UserActivity.html">UserActivity</a><ul class='methods'><li data-type='method'><a href="module-UserActivity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-UserActivity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-UserActivity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-UserActivity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserActivity">restoreUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserChat.html">UserChat</a><ul class='methods'><li data-type='method'><a href="module-UserChat.html#.fetchChatSettings">fetchChatSettings</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.blockedUsers">blockedUsers</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserData">getUserData</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserSignature">getUserSignature</a></li><li data-type='method'><a href="module-UserManagement.html#.isUsernameAvailable">isUsernameAvailable</a></li><li data-type='method'><a href="module-UserManagement.html#.setUserSignature">setUserSignature</a></li><li data-type='method'><a href="module-UserManagement.html#.toggleSignaturePrivate">toggleSignaturePrivate</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.updateDisplayName">updateDisplayName</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserMemberships.html">UserMemberships</a><ul class='methods'><li data-type='method'><a href="module-UserMemberships.html#~fetchMemberships">fetchMemberships</a></li><li data-type='method'><a href="module-UserMemberships.html#~fetchRechargeTokens">fetchRechargeTokens</a></li><li data-type='method'><a href="module-UserMemberships.html#~restorePurchases">restorePurchases</a></li><li data-type='method'><a href="module-UserMemberships.html#~upgradeSubscription">upgradeSubscription</a></li></ul></li><li><a href="module-UserNotifications.html">UserNotifications</a><ul class='methods'><li data-type='method'><a href="module-UserNotifications.html#.deleteNotification">deleteNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchLiveEventPollingState">fetchLiveEventPollingState</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotificationSettings">fetchNotificationSettings</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotifications">fetchNotifications</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchUnreadCount">fetchUnreadCount</a></li><li data-type='method'><a href="module-UserNotifications.html#.markAllNotificationsAsRead">markAllNotificationsAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsRead">markNotificationAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsUnread">markNotificationAsUnread</a></li><li data-type='method'><a href="module-UserNotifications.html#.pauseLiveEventPolling">pauseLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.restoreNotification">restoreNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.startLiveEventPolling">startLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.updateNotificationSetting">updateNotificationSetting</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.deleteProfilePicture">deleteProfilePicture</a></li><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Forums.html">Forums</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3>Interfaces</h3><ul><li><a href="TestUser.html">TestUser</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createTestUser">createTestUser</a></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-Accounts.html">Accounts</a><ul class='methods'><li data-type='method'><a href="module-Accounts.html#~confirmEmailChange">confirmEmailChange</a></li><li data-type='method'><a href="module-Accounts.html#~deleteAccount">deleteAccount</a></li><li data-type='method'><a href="module-Accounts.html#~numberOfActiveUsers">numberOfActiveUsers</a></li><li data-type='method'><a href="module-Accounts.html#~requestEmailChange">requestEmailChange</a></li><li data-type='method'><a href="module-Accounts.html#~resetPassword">resetPassword</a></li><li data-type='method'><a href="module-Accounts.html#~sendAccountSetupEmail">sendAccountSetupEmail</a></li><li data-type='method'><a href="module-Accounts.html#~sendPasswordResetEmail">sendPasswordResetEmail</a></li><li data-type='method'><a href="module-Accounts.html#~setupAccount">setupAccount</a></li><li data-type='method'><a href="module-Accounts.html#~status">status</a></li><li data-type='method'><a href="module-Accounts.html#~toggleStudentView">toggleStudentView</a></li></ul></li><li><a href="module-Artist.html">Artist</a><ul class='methods'><li data-type='method'><a href="module-Artist.html#~fetchArtistBySlug">fetchArtistBySlug</a></li><li data-type='method'><a href="module-Artist.html#~fetchArtistLessons">fetchArtistLessons</a></li><li data-type='method'><a href="module-Artist.html#~fetchArtists">fetchArtists</a></li></ul></li><li><a href="module-Awards.html">Awards</a><ul class='methods'><li data-type='method'><a href="module-Awards.html#~fetchAwardsForUser">fetchAwardsForUser</a></li><li data-type='method'><a href="module-Awards.html#~fetchCertificate">fetchCertificate</a></li><li data-type='method'><a href="module-Awards.html#~getAwardDataForGuidedContent">getAwardDataForGuidedContent</a></li></ul></li><li><a href="module-Config.html">Config</a><ul class='methods'><li data-type='method'><a href="module-Config.html#.initializeService">initializeService</a></li></ul></li><li><a href="module-Content-Services-V2.html">Content-Services-V2</a><ul class='methods'><li data-type='method'><a href="module-Content-Services-V2.html#.getContentRows">getContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getLegacyMethods">getLegacyMethods</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getNewAndUpcoming">getNewAndUpcoming</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getOwnedContent">getOwnedContent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecent">getRecent</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getRecommendedForYou">getRecommendedForYou</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getScheduleContentRows">getScheduleContentRows</a></li><li data-type='method'><a href="module-Content-Services-V2.html#.getTabResults">getTabResults</a></li></ul></li><li><a href="module-Forums.html">Forums</a><ul class='methods'><li data-type='method'><a href="module-Forums.html#~createForumCategory">createForumCategory</a></li><li data-type='method'><a href="module-Forums.html#~createPost">createPost</a></li><li data-type='method'><a href="module-Forums.html#~createThread">createThread</a></li><li data-type='method'><a href="module-Forums.html#~deleteForumCategory">deleteForumCategory</a></li><li data-type='method'><a href="module-Forums.html#~deletePost">deletePost</a></li><li data-type='method'><a href="module-Forums.html#~deleteThread">deleteThread</a></li><li data-type='method'><a href="module-Forums.html#~fetchCommunityGuidelines">fetchCommunityGuidelines</a></li><li data-type='method'><a href="module-Forums.html#~fetchFollowedThreads">fetchFollowedThreads</a></li><li data-type='method'><a href="module-Forums.html#~fetchForumCategories">fetchForumCategories</a></li><li data-type='method'><a href="module-Forums.html#~fetchLatestThreads">fetchLatestThreads</a></li><li data-type='method'><a href="module-Forums.html#~fetchPosts">fetchPosts</a></li><li data-type='method'><a href="module-Forums.html#~fetchThreads">fetchThreads</a></li><li data-type='method'><a href="module-Forums.html#~followThread">followThread</a></li><li data-type='method'><a href="module-Forums.html#~jumpToPost">jumpToPost</a></li><li data-type='method'><a href="module-Forums.html#~likePost">likePost</a></li><li data-type='method'><a href="module-Forums.html#~lockThread">lockThread</a></li><li data-type='method'><a href="module-Forums.html#~markThreadAsRead">markThreadAsRead</a></li><li data-type='method'><a href="module-Forums.html#~pinThread">pinThread</a></li><li data-type='method'><a href="module-Forums.html#~search">search</a></li><li data-type='method'><a href="module-Forums.html#~unfollowThread">unfollowThread</a></li><li data-type='method'><a href="module-Forums.html#~unlikePost">unlikePost</a></li><li data-type='method'><a href="module-Forums.html#~unlockThread">unlockThread</a></li><li data-type='method'><a href="module-Forums.html#~unpinThread">unpinThread</a></li><li data-type='method'><a href="module-Forums.html#~updateForumCategory">updateForumCategory</a></li><li data-type='method'><a href="module-Forums.html#~updatePost">updatePost</a></li><li data-type='method'><a href="module-Forums.html#~updateThread">updateThread</a></li></ul></li><li></li><li></li><li><a href="module-Genre.html">Genre</a><ul class='methods'><li data-type='method'><a href="module-Genre.html#~fetchGenreBySlug">fetchGenreBySlug</a></li><li data-type='method'><a href="module-Genre.html#~fetchGenreLessons">fetchGenreLessons</a></li><li data-type='method'><a href="module-Genre.html#~fetchGenres">fetchGenres</a></li></ul></li><li><a href="module-GuidedCourses.html">GuidedCourses</a></li><li><a href="module-Instructor.html">Instructor</a><ul class='methods'><li data-type='method'><a href="module-Instructor.html#~fetchInstructorBySlug">fetchInstructorBySlug</a></li><li data-type='method'><a href="module-Instructor.html#~fetchInstructorLessons">fetchInstructorLessons</a></li><li data-type='method'><a href="module-Instructor.html#~fetchInstructors">fetchInstructors</a></li></ul></li><li><a href="module-Interests.html">Interests</a><ul class='methods'><li data-type='method'><a href="module-Interests.html#.fetchInterests">fetchInterests</a></li><li data-type='method'><a href="module-Interests.html#.fetchUninterests">fetchUninterests</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsInterested">markContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.markContentAsNotInterested">markContentAsNotInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsInterested">removeContentAsInterested</a></li><li data-type='method'><a href="module-Interests.html#.removeContentAsNotInterested">removeContentAsNotInterested</a></li></ul></li><li><a href="module-LearningPaths.html">LearningPaths</a><ul class='methods'><li data-type='method'><a href="module-LearningPaths.html#~completeLearningPathIntroVideo">completeLearningPathIntroVideo</a></li><li data-type='method'><a href="module-LearningPaths.html#~completeMethodIntroVideo">completeMethodIntroVideo</a></li><li data-type='method'><a href="module-LearningPaths.html#~fetchLearningPathLessons">fetchLearningPathLessons</a></li><li data-type='method'><a href="module-LearningPaths.html#~getActivePath">getActivePath</a></li><li data-type='method'><a href="module-LearningPaths.html#~getDailySession">getDailySession</a></li><li data-type='method'><a href="module-LearningPaths.html#~getEnrichedLearningPath">getEnrichedLearningPath</a></li><li data-type='method'><a href="module-LearningPaths.html#~getLearningPathLessonsByIds">getLearningPathLessonsByIds</a></li><li data-type='method'><a href="module-LearningPaths.html#~mapContentToParent">mapContentToParent</a></li><li data-type='method'><a href="module-LearningPaths.html#~resetAllLearningPaths">resetAllLearningPaths</a></li><li data-type='method'><a href="module-LearningPaths.html#~startLearningPath">startLearningPath</a></li><li data-type='method'><a href="module-LearningPaths.html#~updateActivePath">updateActivePath</a></li><li data-type='method'><a href="module-LearningPaths.html#~updateDailySession">updateDailySession</a></li></ul></li><li><a href="module-Onboarding.html">Onboarding</a><ul class='methods'><li data-type='method'><a href="module-Onboarding.html#~getOnboardingRecommendedContent">getOnboardingRecommendedContent</a></li><li data-type='method'><a href="module-Onboarding.html#~startOnboarding">startOnboarding</a></li><li data-type='method'><a href="module-Onboarding.html#~updateOnboarding">updateOnboarding</a></li><li data-type='method'><a href="module-Onboarding.html#~userOnboardingForBrand">userOnboardingForBrand</a></li></ul></li><li><a href="module-Payments.html">Payments</a><ul class='methods'><li data-type='method'><a href="module-Payments.html#~fetchCustomerPayments">fetchCustomerPayments</a></li></ul></li><li><a href="module-Permissions.html">Permissions</a><ul class='methods'><li data-type='method'><a href="module-Permissions.html#.fetchUserPermissions">fetchUserPermissions</a></li><li data-type='method'><a href="module-Permissions.html#.reset">reset</a></li></ul></li><li><a href="module-Playlists.html">Playlists</a><ul class='methods'><li data-type='method'><a href="module-Playlists.html#.addItemToPlaylist">addItemToPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.createPlaylist">createPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.deletePlaylist">deletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.duplicatePlaylist">duplicatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylist">fetchPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.fetchPlaylistItems">fetchPlaylistItems</a></li><li data-type='method'><a href="module-Playlists.html#.fetchUserPlaylists">fetchUserPlaylists</a></li><li data-type='method'><a href="module-Playlists.html#.togglePlaylistPrivate">togglePlaylistPrivate</a></li><li data-type='method'><a href="module-Playlists.html#.undeletePlaylist">undeletePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#.updatePlaylist">updatePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~deleteItemsFromPlaylist">deleteItemsFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~likePlaylist">likePlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~reportPlaylist">reportPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~restoreItemFromPlaylist">restoreItemFromPlaylist</a></li><li data-type='method'><a href="module-Playlists.html#~unlikePlaylist">unlikePlaylist</a></li></ul></li><li><a href="module-ProgressRow.html">ProgressRow</a></li><li><a href="module-Railcontent-Services.html">Railcontent-Services</a><ul class='methods'><li data-type='method'><a href="module-Railcontent-Services.html#.assignModeratorToComment">assignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.closeComment">closeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.createComment">createComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.deleteComment">deleteComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.editComment">editComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchAllCompletedStates">fetchAllCompletedStates</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCarouselCardData">fetchCarouselCardData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComment">fetchComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCommentRelies">fetchCommentRelies</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchComments">fetchComments</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedContent">fetchCompletedContent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchCompletedState">fetchCompletedState</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentInProgress">fetchContentInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchContentPageUserData">fetchContentPageUserData</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchNextContentDataForParent">fetchNextContentDataForParent</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchRecentUserActivities">fetchRecentUserActivities</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchSongsInProgress">fetchSongsInProgress</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchTopComment">fetchTopComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserAward">fetchUserAward</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserBadges">fetchUserBadges</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.fetchUserPracticeNotes">fetchUserPracticeNotes</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.likeComment">likeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.openComment">openComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentComplete">postContentComplete</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentReset">postContentReset</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentRestore">postContentRestore</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.postContentStart">postContentStart</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.replyToComment">replyToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.reportComment">reportComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.restoreComment">restoreComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.setStudentViewForUser">setStudentViewForUser</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unassignModeratorToComment">unassignModeratorToComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#.unlikeComment">unlikeComment</a></li><li data-type='method'><a href="module-Railcontent-Services.html#~fetchLastInteractedChild">fetchLastInteractedChild</a></li></ul></li><li><a href="module-Sanity-Services.html">Sanity-Services</a><ul class='methods'><li data-type='method'><a href="module-Sanity-Services.html#.fetchAll">fetchAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllFilterOptions">fetchAllFilterOptions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchAllPacks">fetchAllPacks</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentId">fetchByRailContentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByRailContentIds">fetchByRailContentIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchByReference">fetchByReference</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchComingSoon">fetchComingSoon</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchCommentModContentData">fetchCommentModContentData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchFoundation">fetchFoundation</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLeaving">fetchLeaving</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonContent">fetchLessonContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchLessonsFeaturingThisContent">fetchLessonsFeaturingThisContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMetadata">fetchMetadata</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethod">fetchMethod</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildren">fetchMethodChildren</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodChildrenIds">fetchMethodChildrenIds</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodPreviousNextLesson">fetchMethodPreviousNextLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2IntroVideo">fetchMethodV2IntroVideo</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2Structure">fetchMethodV2Structure</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchMethodV2StructureFromId">fetchMethodV2StructureFromId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNewReleases">fetchNewReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchNextPreviousLesson">fetchNextPreviousLesson</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOtherSongVersions">fetchOtherSongVersions</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchOwnedContent">fetchOwnedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackAll">fetchPackAll</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchPackData">fetchPackData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedLessons">fetchRelatedLessons</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedRecommendedContent">fetchRelatedRecommendedContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchRelatedSongs">fetchRelatedSongs</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchReturning">fetchReturning</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSanity">fetchSanity</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchScheduledReleases">fetchScheduledReleases</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchShowsData">fetchShowsData</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSiblingContent">fetchSiblingContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongArtistCount">fetchSongArtistCount</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchSongById">fetchSongById</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchTopLevelParentId">fetchTopLevelParentId</a></li><li data-type='method'><a href="module-Sanity-Services.html#.fetchUpcomingEvents">fetchUpcomingEvents</a></li><li data-type='method'><a href="module-Sanity-Services.html#.jumpToContinueContent">jumpToContinueContent</a></li><li data-type='method'><a href="module-Sanity-Services.html#~fetchRelatedByLicense">fetchRelatedByLicense</a></li><li data-type='method'><a href="module-Sanity-Services.html#~getQueryFromPage">getQueryFromPage</a></li></ul></li><li><a href="module-Sessions.html">Sessions</a><ul class='methods'><li data-type='method'><a href="module-Sessions.html#.login">login</a></li><li data-type='method'><a href="module-Sessions.html#.logout">logout</a></li></ul></li><li><a href="module-UserActivity.html">UserActivity</a><ul class='methods'><li data-type='method'><a href="module-UserActivity.html#.calculateLongestStreaks">calculateLongestStreaks</a></li><li data-type='method'><a href="module-UserActivity.html#.createPracticeNotes">createPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.deletePracticeSession">deletePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.deleteUserActivity">deleteUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeNotes">getPracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.getPracticeSessions">getPracticeSessions</a></li><li data-type='method'><a href="module-UserActivity.html#.getProgressRows">getProgressRows</a></li><li data-type='method'><a href="module-UserActivity.html#.getRecentActivity">getRecentActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserMonthlyStats">getUserMonthlyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.getUserWeeklyStats">getUserWeeklyStats</a></li><li data-type='method'><a href="module-UserActivity.html#.pinProgressRow">pinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserActivity">recordUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.recordUserPractice">recordUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.removeUserPractice">removeUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.restorePracticeSession">restorePracticeSession</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserActivity">restoreUserActivity</a></li><li data-type='method'><a href="module-UserActivity.html#.restoreUserPractice">restoreUserPractice</a></li><li data-type='method'><a href="module-UserActivity.html#.unpinProgressRow">unpinProgressRow</a></li><li data-type='method'><a href="module-UserActivity.html#.updatePracticeNotes">updatePracticeNotes</a></li><li data-type='method'><a href="module-UserActivity.html#.updateUserPractice">updateUserPractice</a></li></ul></li><li><a href="module-UserChat.html">UserChat</a><ul class='methods'><li data-type='method'><a href="module-UserChat.html#.fetchChatSettings">fetchChatSettings</a></li></ul></li><li><a href="module-UserManagement.html">UserManagement</a><ul class='methods'><li data-type='method'><a href="module-UserManagement.html#.blockUser">blockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.blockedUsers">blockedUsers</a></li><li data-type='method'><a href="module-UserManagement.html#.deletePicture">deletePicture</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserData">getUserData</a></li><li data-type='method'><a href="module-UserManagement.html#.getUserSignature">getUserSignature</a></li><li data-type='method'><a href="module-UserManagement.html#.isUsernameAvailable">isUsernameAvailable</a></li><li data-type='method'><a href="module-UserManagement.html#.setUserSignature">setUserSignature</a></li><li data-type='method'><a href="module-UserManagement.html#.toggleSignaturePrivate">toggleSignaturePrivate</a></li><li data-type='method'><a href="module-UserManagement.html#.unblockUser">unblockUser</a></li><li data-type='method'><a href="module-UserManagement.html#.updateDisplayName">updateDisplayName</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPicture">uploadPicture</a></li><li data-type='method'><a href="module-UserManagement.html#.uploadPictureFromS3">uploadPictureFromS3</a></li></ul></li><li><a href="module-UserMemberships.html">UserMemberships</a><ul class='methods'><li data-type='method'><a href="module-UserMemberships.html#~fetchMemberships">fetchMemberships</a></li><li data-type='method'><a href="module-UserMemberships.html#~fetchRechargeTokens">fetchRechargeTokens</a></li><li data-type='method'><a href="module-UserMemberships.html#~restorePurchases">restorePurchases</a></li><li data-type='method'><a href="module-UserMemberships.html#~upgradeSubscription">upgradeSubscription</a></li></ul></li><li><a href="module-UserNotifications.html">UserNotifications</a><ul class='methods'><li data-type='method'><a href="module-UserNotifications.html#.deleteNotification">deleteNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchLiveEventPollingState">fetchLiveEventPollingState</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotificationSettings">fetchNotificationSettings</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchNotifications">fetchNotifications</a></li><li data-type='method'><a href="module-UserNotifications.html#.fetchUnreadCount">fetchUnreadCount</a></li><li data-type='method'><a href="module-UserNotifications.html#.markAllNotificationsAsRead">markAllNotificationsAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsRead">markNotificationAsRead</a></li><li data-type='method'><a href="module-UserNotifications.html#.markNotificationAsUnread">markNotificationAsUnread</a></li><li data-type='method'><a href="module-UserNotifications.html#.pauseLiveEventPolling">pauseLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.restoreNotification">restoreNotification</a></li><li data-type='method'><a href="module-UserNotifications.html#.startLiveEventPolling">startLiveEventPolling</a></li><li data-type='method'><a href="module-UserNotifications.html#.updateNotificationSetting">updateNotificationSetting</a></li></ul></li><li><a href="module-UserProfile.html">UserProfile</a><ul class='methods'><li data-type='method'><a href="module-UserProfile.html#.deleteProfilePicture">deleteProfilePicture</a></li><li data-type='method'><a href="module-UserProfile.html#.otherStats">otherStats</a></li></ul></li></ul><h3>Namespaces</h3><ul><li><a href="ContentOrganization.html">ContentOrganization</a></li><li><a href="Forums.html">Forums</a></li><li><a href="Gamification.html">Gamification</a></li><li><a href="UserManagementSystem.html">UserManagementSystem</a></li></ul><h3>Interfaces</h3><ul><li><a href="TestUser.html">TestUser</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createTestUser">createTestUser</a></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -69,19 +69,16 @@ import {
69
69
  SONG_TYPES,
70
70
  SONG_TYPES_WITH_CHILDREN,
71
71
  } from '../contentTypeConfig.js'
72
- import {fetchSimilarItems, recommendations} from './recommendations.js'
72
+ import { fetchSimilarItems, recommendations } from './recommendations.js'
73
73
  import { processMetadata, typeWithSortOrder } from '../contentMetaData.js'
74
74
 
75
75
  import { globalConfig } from './config.js'
76
76
 
77
- import {
78
- fetchNextContentDataForParent,
79
- fetchHandler,
80
- } from './railcontent.js'
77
+ import { fetchNextContentDataForParent, fetchHandler } from './railcontent.js'
81
78
  import { arrayToStringRepresentation, FilterBuilder } from '../filterBuilder.js'
82
- import { fetchUserPermissions } from './user/permissions.js'
79
+ import { getPermissionsAdapter } from './permissions/index.ts'
83
80
  import { getAllCompleted, getAllStarted, getAllStartedOrCompleted } from './contentProgress.js'
84
- import {fetchRecentActivitiesActiveTabs} from "./userActivity.js";
81
+ import { fetchRecentActivitiesActiveTabs } from './userActivity.js'
85
82
 
86
83
  /**
87
84
  * Exported functions that are excluded from index generation.
@@ -209,30 +206,6 @@ function getQueryFromPage(pageNumber, contentPerPage) {
209
206
  return result
210
207
  }
211
208
 
212
- /**
213
- * Fetch all artists with lessons available for a specific brand.
214
- *
215
- * @param {string} brand - The brand for which to fetch artists.
216
- * @returns {Promise&lt;Object|null>} - A promise that resolves to an array of artist objects or null if not found.
217
- *
218
- * @example
219
- * fetchArtists('drumeo')
220
- * .then(artists => console.log(artists))
221
- * .catch(error => console.error(error));
222
- */
223
- export async function fetchArtists(brand) {
224
- const filter = await new FilterBuilder(
225
- `_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)`,
226
- { bypassPermissions: true }
227
- ).buildFilter()
228
- const query = `
229
- *[_type == "artist"]{
230
- name,
231
- "lessonsCount": count(*[${filter}])
232
- }[lessonsCount > 0] |order(lower(name)) `
233
- return fetchSanity(query, true, { processNeedAccess: false })
234
- }
235
-
236
209
  /**
237
210
  * Fetch current number of artists for songs within a brand.
238
211
  * @param {string} brand - The current brand.
@@ -382,7 +355,7 @@ export async function fetchNewReleases(
382
355
  web_url_path,
383
356
  "permission_id": permission[]->railcontent_id,
384
357
  `
385
- const query = buildRawQuery(filter, fields, {sortOrder: sortOrder, start, end: end})
358
+ const query = buildRawQuery(filter, fields, { sortOrder: sortOrder, start, end: end })
386
359
  return fetchSanity(query, true)
387
360
  }
388
361
 
@@ -523,17 +496,26 @@ export async function fetchByRailContentId(id, contentType) {
523
496
  * .then(contents => console.log(contents))
524
497
  * .catch(error => console.error(error));
525
498
  */
526
- export async function fetchByRailContentIds(ids, contentType = undefined, brand = undefined, includePermissionsAndStatusFilter = false) {
499
+ export async function fetchByRailContentIds(
500
+ ids,
501
+ contentType = undefined,
502
+ brand = undefined,
503
+ includePermissionsAndStatusFilter = false
504
+ ) {
527
505
  if (!ids?.length) {
528
506
  return []
529
507
  }
530
- ids = [...new Set(ids.filter(item => item !== null &amp;&amp; item !== undefined))];
508
+ ids = [...new Set(ids.filter((item) => item !== null &amp;&amp; item !== undefined))]
531
509
  const idsString = ids.join(',')
532
510
  const brandFilter = brand ? ` &amp;&amp; brand == "${brand}"` : ''
533
- const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {pullFutureContent: true}).buildFilter()
511
+ const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {
512
+ pullFutureContent: true,
513
+ }).buildFilter()
534
514
  const fields = await getFieldsForContentTypeWithFilteredChildren(contentType, true)
535
515
  const baseFilter = `railcontent_id in [${idsString}]${brandFilter}`
536
- const finalFilter = includePermissionsAndStatusFilter ? await new FilterBuilder(baseFilter).buildFilter() : baseFilter
516
+ const finalFilter = includePermissionsAndStatusFilter
517
+ ? await new FilterBuilder(baseFilter).buildFilter()
518
+ : baseFilter
537
519
  const query = `*[
538
520
  ${finalFilter}
539
521
  ]{
@@ -543,22 +525,22 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
543
525
  live_event_end_time,
544
526
  }`
545
527
 
546
- console.log('ids query', query)
547
528
  const customPostProcess = (results) => {
548
- const now = getSanityDate(new Date(), false);
529
+ const now = getSanityDate(new Date(), false)
549
530
  const liveProcess = (result) => {
550
531
  if (result.live_event_start_time &amp;&amp; result.live_event_end_time) {
551
- result.isLive =
552
- result.live_event_start_time &lt;= now &amp;&amp;
553
- result.live_event_end_time >= now;
532
+ result.isLive = result.live_event_start_time &lt;= now &amp;&amp; result.live_event_end_time >= now
554
533
  } else {
555
- result.isLive = false;
534
+ result.isLive = false
556
535
  }
557
- return result;
558
- };
559
- return results.map(liveProcess);
536
+ return result
537
+ }
538
+ return results.map(liveProcess)
560
539
  }
561
- const results = await fetchSanity(query, true, { customPostProcess: customPostProcess })
540
+ const results = await fetchSanity(query, true, {
541
+ customPostProcess: customPostProcess,
542
+ processNeedAccess: true,
543
+ })
562
544
 
563
545
  const sortFuction = function compare(a, b) {
564
546
  const indexA = ids.indexOf(a['id'])
@@ -574,13 +556,18 @@ export async function fetchByRailContentIds(ids, contentType = undefined, brand
574
556
  return sortedResults
575
557
  }
576
558
 
577
- export async function fetchContentRows(brand, pageName, contentRowSlug)
578
- {
559
+ export async function fetchContentRows(brand, pageName, contentRowSlug) {
579
560
  if (pageName === 'lessons') pageName = 'lesson'
580
561
  if (pageName === 'songs') pageName = 'song'
581
562
  const rowString = contentRowSlug ? ` &amp;&amp; slug.current == "${contentRowSlug.toLowerCase()}"` : ''
582
- const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {pullFutureContent: true}).buildFilter()
583
- const childFilter = await new FilterBuilder('', {isChildrenFilter: true}).buildFilter()
563
+ const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`, {
564
+ pullFutureContent: true,
565
+ showMembershipRestrictedContent: true,
566
+ }).buildFilter()
567
+ const childFilter = await new FilterBuilder('', {
568
+ isChildrenFilter: true,
569
+ showMembershipRestrictedContent: true,
570
+ }).buildFilter()
584
571
  const query = `*[_type == 'recommended-content-row' &amp;&amp; brand == '${brand}' &amp;&amp; type == '${pageName}'${rowString}]{
585
572
  brand,
586
573
  name,
@@ -593,11 +580,9 @@ export async function fetchContentRows(brand, pageName, contentRowSlug)
593
580
  'lesson_count': coalesce(count(*[${lessonCountFilter}]), 0),
594
581
  },
595
582
  }`
596
- return fetchSanity(query, true)
583
+ return fetchSanity(query, true, { processNeedAccess: true })
597
584
  }
598
585
 
599
-
600
-
601
586
  /**
602
587
  * Fetch all content for a specific brand and type with pagination, search, and grouping options.
603
588
  * @param {string} brand - The brand for which to fetch content.
@@ -666,9 +651,7 @@ export async function fetchAll(
666
651
  } else if (type === 'pack') {
667
652
  typeFilter = `&amp;&amp; (_type == 'pack' || _type == 'semester-pack')`
668
653
  } else {
669
- typeFilter = type
670
- ? `&amp;&amp; _type == '${type}'`
671
- : ''
654
+ typeFilter = type ? `&amp;&amp; _type == '${type}'` : ''
672
655
  }
673
656
 
674
657
  // Construct the search filter
@@ -787,7 +770,7 @@ async function getProgressFilter(progress, progressIds) {
787
770
  return `&amp;&amp; (railcontent_id in [${ids.join(',')}])`
788
771
  }
789
772
  case 'incomplete': {
790
- const ids = progressIds !== undefined ? progressIds :await getAllStarted()
773
+ const ids = progressIds !== undefined ? progressIds : await getAllStarted()
791
774
  return `&amp;&amp; railcontent_id in [${ids.join(',')}]`
792
775
  }
793
776
  default:
@@ -886,7 +869,9 @@ export async function fetchAllFilterOptions(
886
869
 
887
870
  const includedFieldsFilter = filters?.length ? filtersToGroq(filters) : undefined
888
871
  const progressFilter = progressIds ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
889
- const isAdmin = (await fetchUserPermissions()).isAdmin
872
+ const adapter = getPermissionsAdapter()
873
+ const userPermissionsData = await adapter.fetchUserPermissions()
874
+ const isAdmin = adapter.isAdmin(userPermissionsData)
890
875
 
891
876
  const constructCommonFilter = (excludeFilter) => {
892
877
  const filterWithoutOption = excludeFilter
@@ -951,6 +936,7 @@ export async function fetchFoundation(slug) {
951
936
  * @param {string} slug - The slug of the method.
952
937
  * @returns {Promise&lt;Object|null>} - The fetched methods data or null if not found.
953
938
  */
939
+ //todo BEH-1446 depreciated. remove all old method functions
954
940
  export async function fetchMethod(brand, slug) {
955
941
  const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
956
942
 
@@ -1154,7 +1140,11 @@ export async function jumpToContinueContent(railcontentId) {
1154
1140
  * .catch(error => console.error(error));
1155
1141
  */
1156
1142
  export async function fetchLessonContent(railContentId, { addParent = false } = {}) {
1157
- const filterParams = { isSingle: true, pullFutureContent: true }
1143
+ const filterParams = {
1144
+ isSingle: true,
1145
+ pullFutureContent: true,
1146
+ showMembershipRestrictedContent: true,
1147
+ }
1158
1148
 
1159
1149
  const parentQuery = addParent
1160
1150
  ? `"parent_content_data": *[railcontent_id in [...(^.parent_content_data[].id)]]{
@@ -1215,7 +1205,7 @@ export async function fetchLessonContent(railContentId, { addParent = false } =
1215
1205
  return result
1216
1206
  }
1217
1207
 
1218
- return fetchSanity(query, false, { customPostProcess: chapterProcess })
1208
+ return fetchSanity(query, false, { customPostProcess: chapterProcess, processNeedAccess: true })
1219
1209
  }
1220
1210
 
1221
1211
  /**
@@ -1294,7 +1284,7 @@ async function fetchRelatedByLicense(railcontentId, brand, onlyUseSongTypes, cou
1294
1284
  *[${filterSongTypesWithSameLicense}]->{${queryFields}}|order(published_on desc, title asc)[0...${count}],
1295
1285
  }[0...1]`
1296
1286
  const results = await fetchSanity(query, false)
1297
- return results ? results['related_by_license'] ?? [] : []
1287
+ return results ? (results['related_by_license'] ?? []) : []
1298
1288
  }
1299
1289
 
1300
1290
  /**
@@ -1303,17 +1293,24 @@ async function fetchRelatedByLicense(railcontentId, brand, onlyUseSongTypes, cou
1303
1293
  * @param {string} brand - The current brand.
1304
1294
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
1305
1295
  */
1306
- export async function fetchSiblingContent(railContentId, brand= null)
1307
- {
1296
+ export async function fetchSiblingContent(railContentId, brand = null) {
1308
1297
  const filterGetParent = await new FilterBuilder(`references(^._id) &amp;&amp; _type == ^.parent_type`, {
1309
- pullFutureContent: true
1310
- }).buildFilter()
1311
- const filterForParentList = await new FilterBuilder(`references(^._id) &amp;&amp; _type == ^.parent_type`, {
1312
1298
  pullFutureContent: true,
1313
- isParentFilter: true,
1299
+ showMembershipRestrictedContent: true, // Show parent even without permissions
1314
1300
  }).buildFilter()
1301
+ const filterForParentList = await new FilterBuilder(
1302
+ `references(^._id) &amp;&amp; _type == ^.parent_type`,
1303
+ {
1304
+ pullFutureContent: true,
1305
+ isParentFilter: true,
1306
+ showMembershipRestrictedContent: true, // Show parent even without permissions
1307
+ }
1308
+ ).buildFilter()
1315
1309
 
1316
- const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
1310
+ const childrenFilter = await new FilterBuilder(``, {
1311
+ isChildrenFilter: true,
1312
+ showMembershipRestrictedContent: true, // Show all lessons in sidebar, need_access applied on individual page
1313
+ }).buildFilter()
1317
1314
 
1318
1315
  const brandString = brand ? ` &amp;&amp; brand == "${brand}"` : ''
1319
1316
  const queryFields = `_id, "id":railcontent_id, published_on, "instructor": instructor[0]->name, title, "thumbnail":thumbnail.asset->url, length_in_seconds, status, "type": _type, difficulty, difficulty_string, artist->, "permission_id": permission[]->railcontent_id, "genre": genre[]->name, "parent_id": parent_content_data[0].id`
@@ -1327,7 +1324,7 @@ export async function fetchSiblingContent(railContentId, brand= null)
1327
1324
  "related_lessons" : *[${filterGetParent}][0].child[${childrenFilter}]->{${queryFields}}
1328
1325
  }`
1329
1326
 
1330
- let result = await fetchSanity(query, false)
1327
+ let result = await fetchSanity(query, false, { processNeedAccess: true })
1331
1328
 
1332
1329
  //there's no way in sanity to retrieve the index of an array, so we must calculate after fetch
1333
1330
  if (result['for-calculations'] &amp;&amp; result['for-calculations']['parents-list']) {
@@ -1351,15 +1348,16 @@ export async function fetchSiblingContent(railContentId, brand= null)
1351
1348
  * @param {string} railContentId - The RailContent ID of the current lesson.
1352
1349
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
1353
1350
  */
1354
- export async function fetchRelatedLessons(railContentId)
1355
- {
1351
+ export async function fetchRelatedLessons(railContentId) {
1356
1352
  const defaultFilterFields = `_type==^._type &amp;&amp; brand == ^.brand &amp;&amp; railcontent_id != ${railContentId}`
1357
1353
 
1358
1354
  const filterSameArtist = await new FilterBuilder(
1359
- `${defaultFilterFields} &amp;&amp; references(^.artist->_id)`
1355
+ `${defaultFilterFields} &amp;&amp; references(^.artist->_id)`,
1356
+ { showMembershipRestrictedContent: true }
1360
1357
  ).buildFilter()
1361
1358
  const filterSameGenre = await new FilterBuilder(
1362
- `${defaultFilterFields} &amp;&amp; references(^.genre[]->_id)`
1359
+ `${defaultFilterFields} &amp;&amp; references(^.genre[]->_id)`,
1360
+ { showMembershipRestrictedContent: true }
1363
1361
  ).buildFilter()
1364
1362
 
1365
1363
  const queryFields = `_id, "id":railcontent_id, published_on, "instructor": instructor[0]->name, title, "thumbnail":thumbnail.asset->url, length_in_seconds, status, "type": _type, difficulty, difficulty_string, railcontent_id, artist->,"permission_id": permission[]->railcontent_id,_type, "genre": genre[]->name`
@@ -1371,7 +1369,7 @@ export async function fetchRelatedLessons(railContentId)
1371
1369
  ...(*[${filterSameGenre}]{${queryFields}}|order(published_on desc, title asc)[0...10]),
1372
1370
  ])[0...10]}`
1373
1371
 
1374
- return await fetchSanity(query, false)
1372
+ return await fetchSanity(query, false, { processNeedAccess: true })
1375
1373
  }
1376
1374
 
1377
1375
  /**
@@ -1396,11 +1394,16 @@ export async function fetchAllPacks(
1396
1394
  const start = (page - 1) * limit
1397
1395
  const end = start + limit
1398
1396
 
1399
- const query = await buildQuery(filter, filterParams, await getFieldsForContentTypeWithFilteredChildren('pack'), {
1400
- sortOrder: sortOrder,
1401
- start,
1402
- end,
1403
- })
1397
+ const query = await buildQuery(
1398
+ filter,
1399
+ filterParams,
1400
+ await getFieldsForContentTypeWithFilteredChildren('pack'),
1401
+ {
1402
+ sortOrder: sortOrder,
1403
+ start,
1404
+ end,
1405
+ }
1406
+ )
1404
1407
  return fetchSanity(query, true)
1405
1408
  }
1406
1409
 
@@ -1506,45 +1509,6 @@ export async function fetchPackData(id) {
1506
1509
  return fetchSanity(query, false)
1507
1510
  }
1508
1511
 
1509
- /**
1510
- * Fetch the data needed for the coach screen.
1511
- * @param {string} brand - The brand for which to fetch coach lessons
1512
- * @param {string} id - The Railcontent ID of the coach
1513
- * @returns {Promise&lt;Object|null>} - The lessons for the instructor or null if not found.
1514
- * @param {Object} params - Parameters for pagination, filtering and sorting.
1515
- * @param {string} [params.sortOrder="-published_on"] - The field to sort the lessons by.
1516
- * @param {string} [params.searchTerm=""] - The search term to filter content by title.
1517
- * @param {number} [params.page=1] - The page number for pagination.
1518
- * @param {number} [params.limit=10] - The number of items per page.
1519
- * @param {Array&lt;string>} [params.includedFields=[]] - Additional filters to apply to the query in the format of a key,value array. eg. ['difficulty,Intermediate', 'genre,rock'].
1520
- *
1521
- * @example
1522
- * fetchCoachLessons('coach123')
1523
- * .then(lessons => console.log(lessons))
1524
- * .catch(error => console.error(error));
1525
- */
1526
- export async function fetchCoachLessons(
1527
- brand,
1528
- id,
1529
- { sortOrder = '-published_on', searchTerm = '', page = 1, limit = 20, includedFields = [] } = {}
1530
- ) {
1531
- const fieldsString = getFieldsForContentType()
1532
- const start = (page - 1) * limit
1533
- const end = start + limit
1534
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1535
- const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1536
- const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} &amp;&amp; references(*[_type=='instructor' &amp;&amp; railcontent_id == ${id}]._id)`
1537
- const filterWithRestrictions = await new FilterBuilder(filter).buildFilter()
1538
-
1539
- sortOrder = getSortOrder(sortOrder, brand)
1540
- const query = buildEntityAndTotalQuery(filterWithRestrictions, fieldsString, {
1541
- sortOrder: sortOrder,
1542
- start: start,
1543
- end: end,
1544
- })
1545
- return fetchSanity(query, true)
1546
- }
1547
-
1548
1512
  /**
1549
1513
  * Fetch the data needed for the coach screen.
1550
1514
  * @param {string} id - The Railcontent ID of the coach
@@ -1577,149 +1541,33 @@ export async function fetchByReference(
1577
1541
  }
1578
1542
 
1579
1543
  /**
1580
- * Fetch the artist's lessons.
1581
- * @param {string} brand - The brand for which to fetch lessons.
1582
- * @param {string} name - The name of the artist
1583
- * @param {string} contentType - The type of the lessons we need to get from the artist. If not defined, groq will get lessons from all content types
1584
- * @param {Object} params - Parameters for sorting, searching, pagination and filtering.
1585
- * @param {string} [params.sort="-published_on"] - The field to sort the lessons by.
1586
- * @param {string} [params.searchTerm=""] - The search term to filter the lessons.
1587
- * @param {number} [params.page=1] - The page number for pagination.
1588
- * @param {number} [params.limit=10] - The number of items per page.
1589
- * @param {Array&lt;string>} [params.includedFields=[]] - Additional filters to apply to the query in the format of a key,value array. eg. ['difficulty,Intermediate', 'genre,rock'].
1590
- * @param {Array&lt;number>} [params.progressIds] - The ids of the lessons that are in progress or completed
1591
- * @returns {Promise&lt;Object|null>} - The lessons for the artist and some details about the artist (name and thumbnail).
1592
1544
  *
1593
- * @example
1594
- * fetchArtistLessons('drumeo', '10 Years', 'song', {'-published_on', '', 1, 10, ["difficulty,Intermediate"], [232168, 232824, 303375, 232194, 393125]})
1595
- * .then(lessons => console.log(lessons))
1596
- * .catch(error => console.error(error));
1597
- */
1598
- export async function fetchArtistLessons(
1599
- brand,
1600
- name,
1601
- contentType,
1602
- {
1603
- sort = '-published_on',
1604
- searchTerm = '',
1605
- page = 1,
1606
- limit = 10,
1607
- includedFields = [],
1608
- progressIds = undefined,
1609
- } = {}
1610
- ) {
1611
- const fieldsString = DEFAULT_FIELDS.join(',')
1612
- const start = (page - 1) * limit
1613
- const end = start + limit
1614
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1615
- const sortOrder = getSortOrder(sort, brand)
1616
- const addType =
1617
- contentType &amp;&amp; Array.isArray(contentType)
1618
- ? `_type in ['${contentType.join("', '")}'] &amp;&amp;`
1619
- : contentType
1620
- ? `_type == '${contentType}' &amp;&amp; `
1621
- : ''
1622
- const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1623
-
1624
- // limits the results to supplied progressIds for started &amp; completed filters
1625
- const progressFilter =
1626
- progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
1627
- const now = getSanityDate(new Date())
1628
- const query = `{
1629
- "entity":
1630
- *[_type == 'artist' &amp;&amp; name == '${name}']
1631
- {'type': _type, name, 'thumbnail':thumbnail_url.asset->url,
1632
- 'lessons_count': count(*[${addType} brand == '${brand}' &amp;&amp; references(^._id)]),
1633
- 'lessons': *[${addType} brand == '${brand}' &amp;&amp; references(^._id) &amp;&amp; (status in ['published'] || (status == 'scheduled' &amp;&amp; defined(published_on) &amp;&amp; published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
1634
- [${start}...${end}]}
1635
- |order(${sortOrder})f
1636
- }`
1637
- return fetchSanity(query, true)
1638
- }
1639
-
1640
- /**
1641
- * Fetch the genre's lessons.
1642
- * @param {string} brand - The brand for which to fetch lessons.
1643
- * @param {string} name - The name of the genre
1644
- * @param {Object} params - Parameters for sorting, searching, pagination and filtering.
1645
- * @param {string} [params.sort="-published_on"] - The field to sort the lessons by.
1646
- * @param {string} [params.searchTerm=""] - The search term to filter the lessons.
1647
- * @param {number} [params.page=1] - The page number for pagination.
1648
- * @param {number} [params.limit=10] - The number of items per page.
1649
- * @param {Array&lt;string>} [params.includedFields=[]] - Additional filters to apply to the query in the format of a key,value array. eg. ['difficulty,Intermediate', 'genre,rock'].
1650
- * @param {Array&lt;number>} [params.progressIds] - The ids of the lessons that are in progress or completed
1651
- * @returns {Promise&lt;Object|null>} - The lessons for the artist and some details about the artist (name and thumbnail).
1545
+ * Return the top level parent content railcontent_id.
1546
+ * Ignores learning-path-v2 parents.
1547
+ * ex: if railcontentId is of type 'skill-pack-lesson', return the corresponding 'skill-pack' railcontent_id
1652
1548
  *
1653
- * @example
1654
- * fetchGenreLessons('drumeo', 'Blues', 'song', {'-published_on', '', 1, 10, ["difficulty,Intermediate"], [232168, 232824, 303375, 232194, 393125]})
1655
- * .then(lessons => console.log(lessons))
1656
- * .catch(error => console.error(error));
1549
+ * @param {int} railcontentId
1550
+ * @returns {Promise&lt;int|null>}
1657
1551
  */
1658
- export async function fetchGenreLessons(
1659
- brand,
1660
- name,
1661
- contentType,
1662
- {
1663
- sort = '-published_on',
1664
- searchTerm = '',
1665
- page = 1,
1666
- limit = 10,
1667
- includedFields = [],
1668
- progressIds = undefined,
1669
- } = {}
1670
- ) {
1671
- const fieldsString = DEFAULT_FIELDS.join(',')
1672
- const start = (page - 1) * limit
1673
- const end = start + limit
1674
- const searchFilter = searchTerm ? `&amp;&amp; title match "${searchTerm}*"` : ''
1675
- const sortOrder = getSortOrder(sort, brand)
1676
- const addType = contentType ? `_type == '${contentType}' &amp;&amp; ` : ''
1677
- const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
1678
- // limits the results to supplied progressIds for started &amp; completed filters
1679
- const progressFilter =
1680
- progressIds !== undefined ? `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : ''
1681
- const now = getSanityDate(new Date())
1682
- const query = `{
1683
- "entity":
1684
- *[_type == 'genre' &amp;&amp; name == '${name}']
1685
- {'type': _type, name, 'thumbnail':thumbnail_url.asset->url,
1686
- 'lessons_count': count(*[${addType} brand == '${brand}' &amp;&amp; references(^._id)]),
1687
- 'lessons': *[${addType} brand == '${brand}' &amp;&amp; references(^._id) &amp;&amp; (status in ['published'] || (status == 'scheduled' &amp;&amp; defined(published_on) &amp;&amp; published_on >= '${now}')) ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{${fieldsString}}
1688
- [${start}...${end}]}
1689
- |order(${sortOrder})
1690
- }`
1691
- return fetchSanity(query, true)
1692
- }
1693
-
1694
1552
  export async function fetchTopLevelParentId(railcontentId) {
1553
+ const parentFilter = "railcontent_id in [...(^.parent_content_data[].id)]"
1695
1554
  const statusFilter = "&amp;&amp; status in ['scheduled', 'published', 'archived', 'unlisted']"
1696
1555
 
1697
1556
  const query = `*[railcontent_id == ${railcontentId}]{
1698
1557
  railcontent_id,
1699
- 'parents': *[^._id in child[]._ref ${statusFilter}]{
1700
- railcontent_id,
1701
- 'parents': *[^._id in child[]._ref ${statusFilter}]{
1702
- railcontent_id,
1703
- 'parents': *[^._id in child[]._ref ${statusFilter}]{
1704
- railcontent_id,
1705
- 'parents': *[^._id in child[]._ref ${statusFilter}]{
1706
- railcontent_id,
1707
- }
1708
- }
1709
- }
1558
+ 'parents': *[${parentFilter} ${statusFilter}]{
1559
+ railcontent_id
1710
1560
  }
1711
1561
  }`
1712
1562
  let response = await fetchSanity(query, false, { processNeedAccess: false })
1713
1563
  if (!response) return null
1714
- let currentLevel = response
1715
- for (let i = 0; i &lt; 4; i++) {
1716
- if (currentLevel['parents'].length > 0) {
1717
- currentLevel = currentLevel['parents'][0]
1718
- } else {
1719
- return currentLevel['railcontent_id']
1720
- }
1564
+ let parents = response['parents']
1565
+ let parentsLength = parents ? response['parents'].length : 0
1566
+ if (parentsLength > 0) {
1567
+ // return the last parent
1568
+ return parents[parentsLength - 1]['railcontent_id']
1721
1569
  }
1722
- return null
1570
+ return response['railcontent_id']
1723
1571
  }
1724
1572
 
1725
1573
  export async function fetchHierarchy(railcontentId) {
@@ -1812,8 +1660,10 @@ export async function fetchCommentModContentData(ids) {
1812
1660
  *
1813
1661
  * @param {string} query - The GROQ query to execute against the Sanity API.
1814
1662
  * @param {boolean} isList - Whether to return an array or a single result.
1815
- * @param {Function} [customPostProcess=null] - custom post process callback
1816
- * @param {boolean} [processNeedAccess=true] - execute the needs_access callback
1663
+ * @param {Object} options - Additional options for fetching data.
1664
+ * @param {Function} [options.customPostProcess=null] - custom post process callback
1665
+ * @param {boolean} [options.processNeedAccess=true] - execute the needs_access callback
1666
+ * @param {boolean} [options.processPageType=true] - execute the page_type callback
1817
1667
  * @returns {Promise&lt;*|null>} - A promise that resolves to the fetched data or null if an error occurs or no results are found.
1818
1668
  *
1819
1669
  * @example
@@ -1826,7 +1676,7 @@ export async function fetchCommentModContentData(ids) {
1826
1676
  export async function fetchSanity(
1827
1677
  query,
1828
1678
  isList,
1829
- { customPostProcess = null, processNeedAccess = true } = {}
1679
+ { customPostProcess = null, processNeedAccess = true, processPageType = true } = {}
1830
1680
  ) {
1831
1681
  // Check the config object before proceeding
1832
1682
  if (!checkSanityConfig(globalConfig)) {
@@ -1848,13 +1698,13 @@ export async function fetchSanity(
1848
1698
  body: JSON.stringify({ query: query }),
1849
1699
  }
1850
1700
 
1701
+ const adapter = getPermissionsAdapter()
1851
1702
  let promisesResult = await Promise.all([
1852
1703
  fetch(url, options),
1853
- processNeedAccess ? fetchUserPermissions() : null,
1704
+ processNeedAccess ? adapter.fetchUserPermissions() : null,
1854
1705
  ])
1855
1706
  const response = promisesResult[0]
1856
- const userPermissions = promisesResult[1]?.permissions
1857
- const isAdmin = promisesResult[1]?.isAdmin
1707
+ const userPermissions = promisesResult[1]
1858
1708
 
1859
1709
  if (!response.ok) {
1860
1710
  throw new Error(`Sanity API error: ${response.status} - ${response.statusText}`)
@@ -1865,25 +1715,32 @@ export async function fetchSanity(
1865
1715
  if (!results) {
1866
1716
  throw new Error('No results found')
1867
1717
  }
1868
- results = processNeedAccess
1869
- ? await needsAccessDecorator(results, userPermissions, isAdmin)
1870
- : results
1871
- results = pageTypeDecorator(results)
1718
+ results = processNeedAccess ? await needsAccessDecorator(results, userPermissions) : results
1719
+ results = processPageType ? pageTypeDecorator(results) : results
1872
1720
  return customPostProcess ? customPostProcess(results) : results
1873
1721
  } else {
1874
1722
  throw new Error('No results found')
1875
1723
  }
1876
1724
  } catch (error) {
1877
- console.error('fetchSanity: Fetch error:', {error, query})
1725
+ console.error('fetchSanity: Fetch error:', { error, query })
1878
1726
  return null
1879
1727
  }
1880
1728
  }
1881
1729
 
1882
- function contentResultsDecorator(results, fieldName, callback)
1883
- {
1730
+ function contentResultsDecorator(results, fieldName, callback) {
1884
1731
  if (Array.isArray(results)) {
1885
1732
  results.forEach((result) => {
1886
- result[fieldName] = callback(result)
1733
+ // Check if this is a content row structure
1734
+ if (result.content &amp;&amp; Array.isArray(result.content)) {
1735
+ // Content rows structure: array of rows, each with a content array
1736
+ result.content.forEach((contentItem) => {
1737
+ if (contentItem) {
1738
+ contentItem[fieldName] = callback(contentItem)
1739
+ }
1740
+ })
1741
+ } else {
1742
+ result[fieldName] = callback(result)
1743
+ }
1887
1744
  })
1888
1745
  } else if (results.entity &amp;&amp; Array.isArray(results.entity)) {
1889
1746
  // Group By
@@ -1907,32 +1764,25 @@ function contentResultsDecorator(results, fieldName, callback)
1907
1764
  return results
1908
1765
  }
1909
1766
 
1910
- function pageTypeDecorator(results)
1911
- {
1912
- return contentResultsDecorator(results, 'page_type', function(content) { return SONG_TYPES_WITH_CHILDREN.includes(content['type']) ? 'song' : 'lesson'})
1767
+ function pageTypeDecorator(results) {
1768
+ return contentResultsDecorator(results, 'page_type', function (content) {
1769
+ return SONG_TYPES_WITH_CHILDREN.includes(content['type']) ? 'song' : 'lesson'
1770
+ })
1913
1771
  }
1914
1772
 
1915
-
1916
- function needsAccessDecorator(results, userPermissions, isAdmin) {
1773
+ function needsAccessDecorator(results, userPermissions) {
1917
1774
  if (globalConfig.sanityConfig.useDummyRailContentMethods) return results
1918
- userPermissions = new Set(userPermissions)
1919
- return contentResultsDecorator(results, 'need_access', function (content) { return doesUserNeedAccessToContent(content, userPermissions, isAdmin) })
1775
+ const adapter = getPermissionsAdapter()
1776
+ return contentResultsDecorator(results, 'need_access', function (content) {
1777
+ return adapter.doesUserNeedAccess(content, userPermissions)
1778
+ })
1920
1779
  }
1921
1780
 
1922
- function doesUserNeedAccessToContent(result, userPermissions, isAdmin) {
1923
- if (isAdmin ?? false) {
1924
- return false
1925
- }
1926
- const permissions = new Set(result?.permission_id ?? [])
1927
- if (permissions.size === 0) {
1928
- return false
1929
- }
1930
- for (let permission of permissions) {
1931
- if (userPermissions.has(permission)) {
1932
- return false
1933
- }
1934
- }
1935
- return true
1781
+ function doesUserNeedAccessToContent(result, userPermissions) {
1782
+ // Legacy function - now delegates to adapter
1783
+ // Kept for backwards compatibility if used elsewhere
1784
+ const adapter = getPermissionsAdapter()
1785
+ return adapter.doesUserNeedAccess(result, userPermissions)
1936
1786
  }
1937
1787
 
1938
1788
  /**
@@ -1974,8 +1824,8 @@ export async function fetchShowsData(brand) {
1974
1824
  * .catch(error => console.error(error));
1975
1825
  */
1976
1826
  export async function fetchMetadata(brand, type) {
1977
- let processedData = processMetadata(brand, type, true)
1978
- if(processedData?.onlyAvailableTabs === true) {
1827
+ let processedData = processMetadata(brand, type, true)
1828
+ if (processedData?.onlyAvailableTabs === true) {
1979
1829
  const activeTabs = await fetchRecentActivitiesActiveTabs()
1980
1830
  processedData.tabs = activeTabs
1981
1831
  }
@@ -2001,7 +1851,7 @@ function arrayJoinWithQuotes(array, delimiter = ',') {
2001
1851
  return wrapped.join(delimiter)
2002
1852
  }
2003
1853
 
2004
- function getSanityDate(date, roundToHourForCaching = true) {
1854
+ export function getSanityDate(date, roundToHourForCaching = true) {
2005
1855
  if (roundToHourForCaching) {
2006
1856
  // We need to set the published on filter date to be a round time so that it doesn't bypass the query cache
2007
1857
  // with every request by changing the filter date every second. I've set it to one minute past the current hour
@@ -2075,13 +1925,19 @@ async function buildQuery(
2075
1925
  return buildRawQuery(filter, fields, { sortOrder, start, end, isSingle })
2076
1926
  }
2077
1927
 
2078
- function buildEntityAndTotalQuery(
1928
+ export function buildEntityAndTotalQuery(
2079
1929
  filter = '',
2080
1930
  fields = '...',
2081
- { sortOrder = 'published_on desc', start = 0, end = 10, isSingle = false, withoutPagination = false }
1931
+ {
1932
+ sortOrder = 'published_on desc',
1933
+ start = 0,
1934
+ end = 10,
1935
+ isSingle = false,
1936
+ withoutPagination = false,
1937
+ }
2082
1938
  ) {
2083
1939
  const sortString = sortOrder ? ` | order(${sortOrder})` : ''
2084
- const countString = isSingle ? '[0...1]' : (withoutPagination ? ``: `[${start}...${end}]`)
1940
+ const countString = isSingle ? '[0...1]' : withoutPagination ? `` : `[${start}...${end}]`
2085
1941
  const query = `{
2086
1942
  "entity": *[${filter}] ${sortString}${countString}
2087
1943
  {
@@ -2198,6 +2054,7 @@ export async function fetchTabData(
2198
2054
  includedFields = [],
2199
2055
  progressIds = undefined,
2200
2056
  progress = 'all',
2057
+ showMembershipRestrictedContent = false,
2201
2058
  } = {}
2202
2059
  ) {
2203
2060
  const start = (page - 1) * limit
@@ -2210,22 +2067,22 @@ export async function fetchTabData(
2210
2067
 
2211
2068
  switch (progress) {
2212
2069
  case 'recent':
2213
- progressIds = await getAllStartedOrCompleted({ brand, onlyIds: true });
2214
- sortOrder = null;
2215
- break;
2070
+ progressIds = await getAllStartedOrCompleted({ brand, onlyIds: true })
2071
+ sortOrder = null
2072
+ break
2216
2073
  case 'incomplete':
2217
- progressIds = await getAllStarted();
2218
- sortOrder = null;
2219
- break;
2074
+ progressIds = await getAllStarted()
2075
+ sortOrder = null
2076
+ break
2220
2077
  case 'completed':
2221
- progressIds = await getAllCompleted();
2222
- sortOrder = null;
2223
- break;
2078
+ progressIds = await getAllCompleted()
2079
+ sortOrder = null
2080
+ break
2224
2081
  }
2225
2082
 
2226
2083
  // limits the results to supplied progressIds for started &amp; completed filters
2227
2084
  const progressFilter = await getProgressFilter(progress, progressIds)
2228
- const fieldsString = getFieldsForContentType('tab-data');
2085
+ const fieldsString = getFieldsForContentType('tab-data')
2229
2086
  const now = getSanityDate(new Date())
2230
2087
 
2231
2088
  // Determine the group by clause
@@ -2234,11 +2091,13 @@ export async function fetchTabData(
2234
2091
  let filter = ''
2235
2092
 
2236
2093
  filter = `brand == "${brand}" &amp;&amp; (defined(railcontent_id)) ${includedFieldsFilter} ${progressFilter}`
2237
- const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
2094
+ const childrenFilter = await new FilterBuilder(``, {
2095
+ isChildrenFilter: true,
2096
+ showMembershipRestrictedContent: true,
2097
+ }).buildFilter()
2238
2098
  const childrenFields = await getChildFieldsForContentType('tab-data')
2239
2099
  const lessonCountFilter = await new FilterBuilder(`_id in ^.child[]._ref`).buildFilter()
2240
- entityFieldsString =
2241
- ` ${fieldsString}
2100
+ entityFieldsString = ` ${fieldsString}
2242
2101
  'children': child[${childrenFilter}]->{ ${childrenFields} 'children': child[${childrenFilter}]->{ ${childrenFields} }, },
2243
2102
  'isLive': live_event_start_time &lt;= "${now}" &amp;&amp; live_event_end_time >= "${now}",
2244
2103
  'lesson_count': coalesce(count(*[${lessonCountFilter}]), 0),
@@ -2250,27 +2109,29 @@ export async function fetchTabData(
2250
2109
  ),
2251
2110
  length_in_seconds
2252
2111
  ),`
2253
- const filterWithRestrictions = await new FilterBuilder(filter, {}).buildFilter()
2112
+ const filterWithRestrictions = await new FilterBuilder(filter, {
2113
+ showMembershipRestrictedContent: true,
2114
+ }).buildFilter()
2254
2115
  query = buildEntityAndTotalQuery(filterWithRestrictions, entityFieldsString, {
2255
2116
  sortOrder: sortOrder,
2256
2117
  start: start,
2257
- end: end
2118
+ end: end,
2258
2119
  })
2259
2120
 
2260
- let results = await fetchSanity(query, true);
2121
+ let results = await fetchSanity(query, true, { processNeedAccess: true })
2261
2122
 
2262
2123
  if (['recent', 'incomplete', 'completed'].includes(progress) &amp;&amp; results.entity.length > 1) {
2263
2124
  const orderMap = new Map(progressIds.map((id, index) => [id, index]))
2264
2125
  results.entity = results.entity
2265
2126
  .sort((a, b) => {
2266
- const aIdx = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER;
2267
- const bIdx = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER;
2268
- return aIdx - bIdx || new Date(b.published_on) - new Date(a.published_on);
2127
+ const aIdx = orderMap.get(a.id) ?? Number.MAX_SAFE_INTEGER
2128
+ const bIdx = orderMap.get(b.id) ?? Number.MAX_SAFE_INTEGER
2129
+ return aIdx - bIdx || new Date(b.published_on) - new Date(a.published_on)
2269
2130
  })
2270
- .slice(start, end);
2131
+ .slice(start, end)
2271
2132
  }
2272
2133
 
2273
- return results;
2134
+ return results
2274
2135
  }
2275
2136
 
2276
2137
  export async function fetchRecent(
@@ -2345,12 +2206,12 @@ export async function fetchShows(brand, type, sort = 'sort') {
2345
2206
  * @returns {Promise&lt;*|null>}
2346
2207
  */
2347
2208
  export async function fetchMethodV2IntroVideo(brand) {
2348
- const type = "method-intro";
2349
- const filter = `_type == '${type}' &amp;&amp; brand == '${brand}'`;
2350
- const fields = getIntroVideoFields('method-v2');
2209
+ const type = 'method-intro'
2210
+ const filter = `_type == '${type}' &amp;&amp; brand == '${brand}'`
2211
+ const fields = getIntroVideoFields('method-v2')
2351
2212
 
2352
- const query = `*[${filter}] { ${fields.join(", ")} }`;
2353
- return fetchSanity(query, false);
2213
+ const query = `*[${filter}] { ${fields.join(', ')} }`
2214
+ return fetchSanity(query, false)
2354
2215
  }
2355
2216
 
2356
2217
  /**
@@ -2359,15 +2220,15 @@ export async function fetchMethodV2IntroVideo(brand) {
2359
2220
  * @returns {Promise&lt;*|null>}
2360
2221
  */
2361
2222
  export async function fetchMethodV2Structure(brand) {
2362
- const _type = "method-v2";
2223
+ const _type = 'method-v2'
2363
2224
  const query = `*[_type == '${_type}' &amp;&amp; brand == '${brand}'][0...1]{
2364
2225
  'sanity_id': _id,
2365
- 'learningPaths': child[]->{
2226
+ 'learning_paths': child[]->{
2366
2227
  'id': railcontent_id,
2367
2228
  'children': child[]->railcontent_id
2368
2229
  }
2369
2230
  }`
2370
- return await fetchSanity(query, false);
2231
+ return await fetchSanity(query, false)
2371
2232
  }
2372
2233
 
2373
2234
  /**
@@ -2379,13 +2240,61 @@ export async function fetchMethodV2StructureFromId(contentId) {
2379
2240
  const _type = "method-v2";
2380
2241
  const query = `*[_type == '${_type}' &amp;&amp; brand == *[railcontent_id == ${contentId}][0].brand][0...1]{
2381
2242
  'sanity_id': _id,
2382
- 'learningPaths': child[]->{
2243
+ 'learning_paths': child[]->{
2383
2244
  'id': railcontent_id,
2384
2245
  'children': child[]->railcontent_id
2385
2246
  }
2386
2247
  }`
2387
2248
  return await fetchSanity(query, false);
2388
2249
  }
2250
+
2251
+ /**
2252
+ * Fetch content owned by the user (excluding membership content).
2253
+ * Shows only content accessible through purchases/entitlements, not through membership.
2254
+ *
2255
+ * @param {string} brand - The brand to filter content by
2256
+ * @param {Object} options - Fetch options
2257
+ * @param {Array&lt;string>} options.type - Content type(s) to filter (optional array, default: [])
2258
+ * @param {number} options.page - Page number (default: 1)
2259
+ * @param {number} options.limit - Items per page (default: 10)
2260
+ * @param {string} options.sort - Sort field and direction (default: '-published_on')
2261
+ * @returns {Promise&lt;Object>} Object with 'entity' (content array) and 'total' (count)
2262
+ */
2263
+ export async function fetchOwnedContent(
2264
+ brand,
2265
+ { type = [], page = 1, limit = 10, sort = '-published_on' } = {}
2266
+ ) {
2267
+ const start = (page - 1) * limit
2268
+ const end = start + limit
2269
+
2270
+ // Determine the sort order
2271
+ const sortOrder = getSortOrder(sort, brand)
2272
+
2273
+ // Build the type filter
2274
+ let typeFilter = ''
2275
+ if (type.length > 0) {
2276
+ const typesString = type.map((t) => `'${t}'`).join(', ')
2277
+ typeFilter = `&amp;&amp; _type in [${typesString}]`
2278
+ }
2279
+
2280
+ // Build the base filter
2281
+ const filter = `brand == "${brand}" ${typeFilter}`
2282
+
2283
+ // Apply owned content filter
2284
+ const filterWithRestrictions = await new FilterBuilder(filter, {
2285
+ showOnlyOwnedContent: true, // Key parameter: exclude membership content
2286
+ }).buildFilter()
2287
+
2288
+ const fieldsString = DEFAULT_FIELDS.join(',')
2289
+
2290
+ const query = buildEntityAndTotalQuery(filterWithRestrictions, fieldsString, {
2291
+ sortOrder: sortOrder,
2292
+ start: start,
2293
+ end: end,
2294
+ })
2295
+
2296
+ return fetchSanity(query, true)
2297
+ }
2389
2298
  </code></pre>
2390
2299
  </article>
2391
2300
  </section>
@@ -2400,7 +2309,7 @@ export async function fetchMethodV2StructureFromId(contentId) {
2400
2309
  <br class="clear">
2401
2310
 
2402
2311
  <footer>
2403
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Wed Nov 19 2025 14:55:35 GMT-0800 (Pacific Standard Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
2312
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Tue Nov 25 2025 19:26:53 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
2404
2313
  </footer>
2405
2314
 
2406
2315
  <script>prettyPrint();</script>