musora-content-services 2.108.0 → 2.110.3

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 (34) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/CLAUDE.md +2 -2
  3. package/package.json +1 -1
  4. package/src/contentMetaData.js +0 -5
  5. package/src/contentTypeConfig.js +11 -73
  6. package/src/index.d.ts +0 -20
  7. package/src/index.js +0 -20
  8. package/src/services/content.js +1 -1
  9. package/src/services/contentAggregator.js +1 -4
  10. package/src/services/railcontent.js +0 -163
  11. package/src/services/sanity.js +258 -7
  12. package/src/services/sync/adapters/factory.ts +6 -6
  13. package/src/services/sync/adapters/lokijs.ts +174 -1
  14. package/src/services/sync/context/providers/durability.ts +1 -0
  15. package/src/services/sync/database/factory.ts +12 -5
  16. package/src/services/sync/effects/index.ts +6 -0
  17. package/src/services/sync/effects/logout-warning.ts +47 -0
  18. package/src/services/sync/errors/boundary.ts +4 -6
  19. package/src/services/sync/errors/index.ts +16 -0
  20. package/src/services/sync/fetch.ts +5 -5
  21. package/src/services/sync/manager.ts +80 -40
  22. package/src/services/sync/repositories/base.ts +1 -8
  23. package/src/services/sync/retry.ts +4 -4
  24. package/src/services/sync/store/index.ts +34 -31
  25. package/src/services/sync/store/push-coalescer.ts +3 -3
  26. package/src/services/sync/store-configs.ts +10 -8
  27. package/src/services/sync/telemetry/flood-prevention.ts +27 -0
  28. package/src/services/sync/telemetry/index.ts +71 -9
  29. package/src/services/sync/telemetry/sampling.ts +2 -6
  30. package/src/services/user/types.d.ts +0 -7
  31. package/test/sync/adapter.ts +2 -34
  32. package/test/sync/initialize-sync-manager.js +8 -25
  33. package/.claude/settings.local.json +0 -9
  34. package/src/services/sync/concurrency-safety.ts +0 -4
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [2.110.3](https://github.com/railroadmedia/musora-content-services/compare/v2.110.2...v2.110.3) (2026-01-05)
6
+
7
+ ### [2.110.2](https://github.com/railroadmedia/musora-content-services/compare/v2.110.1...v2.110.2) (2026-01-05)
8
+
9
+ ### [2.110.1](https://github.com/railroadmedia/musora-content-services/compare/v2.110.0...v2.110.1) (2026-01-05)
10
+
11
+ ## [2.110.0](https://github.com/railroadmedia/musora-content-services/compare/v2.109.0...v2.110.0) (2026-01-05)
12
+
13
+
14
+ ### Features
15
+
16
+ * **BEH-1421:** lesson type migrations ([#660](https://github.com/railroadmedia/musora-content-services/issues/660)) ([7f5ab7e](https://github.com/railroadmedia/musora-content-services/commit/7f5ab7e64693b51aea754e0fb13f10edbd7a7958))
17
+
18
+ ## [2.109.0](https://github.com/railroadmedia/musora-content-services/compare/v2.108.0...v2.109.0) (2026-01-05)
19
+
20
+
21
+ ### Features
22
+
23
+ * **TP-1046:** expose error hooks ([#655](https://github.com/railroadmedia/musora-content-services/issues/655)) ([233fa10](https://github.com/railroadmedia/musora-content-services/commit/233fa1009038448c763d130ec942b9de5a49a875))
24
+
5
25
  ## [2.108.0](https://github.com/railroadmedia/musora-content-services/compare/v2.107.8...v2.108.0) (2026-01-02)
6
26
 
7
27
 
package/CLAUDE.md CHANGED
@@ -329,8 +329,8 @@ import { ContentLike, ContentProgress, Practice, PracticeDayNote } from 'musora-
329
329
  // - TabsProvider: no-op (single "tab" on mobile)
330
330
 
331
331
  const manager = new SyncManager(context, db)
332
- manager.syncStoresWithStrategies(
333
- manager.storesForModels([ContentLike, ContentProgress, Practice, PracticeDayNote]),
332
+ manager.registerStrategies(
333
+ ContentLike, ContentProgress, Practice, PracticeDayNote],
334
334
  [initialStrategy, onlineStrategy, activityStrategy, hourlyPollingStrategy]
335
335
  )
336
336
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.108.0",
3
+ "version": "2.110.3",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -229,11 +229,6 @@ const contentMetadata = {
229
229
  }
230
230
  }
231
231
 
232
- export const typeWithSortOrder = [
233
- 'in-rhythm',
234
- 'diy-drum-experiments',
235
- 'rhythmic-adventures-of-captain-carson',
236
- ]
237
232
 
238
233
  export function processMetadata(brand, type, withFilters = false) {
239
234
  let brandMetaData = contentMetadata[brand]?.[type]
@@ -140,30 +140,15 @@ const contentWithSortField = {
140
140
  export const showsTypes = {
141
141
  drumeo: [
142
142
  'odd-times',
143
- 'drum-fest-international-2022',
144
143
  'spotlight',
145
- 'the-history-of-electronic-drums',
146
- 'backstage-secret',
147
144
  'quick-tips',
148
145
  'question-and-answer',
149
146
  'live',
150
147
  'podcast',
151
- 'solo',
152
148
  'boot-camp',
153
149
  'gear-guide',
154
150
  'performance',
155
- 'in-rhythm',
156
- 'challenges',
157
- 'on-the-road',
158
- 'diy-drum-experiment',
159
- 'rhythmic-adventures-of-captain-carson',
160
151
  'study-the-greats',
161
- 'rhythms-from-another-planet',
162
- 'tama',
163
- 'paiste-cymbals',
164
- 'behind-the-scenes',
165
- 'exploring-beats',
166
- 'sonor',
167
152
  ],
168
153
  pianote: ['student-review', 'question-and-answer'],
169
154
  guitareo: ['student-review', 'question-and-answer', 'archives', 'recording'],
@@ -227,13 +212,11 @@ export const skillLessonTypes = ['skill-pack']
227
212
  export const showsLessonTypes = [
228
213
  'boot-camp',
229
214
  'study-the-greats',
230
- // TODO these require clearing the information with Chris, they weren't part of the old system, but are part of the migration document as SHOWS
231
- // 'gear-guide',
232
- // 'odd-times',
233
- // 'podcast',
234
- // 'spotlight',
235
- // 'study-the-greats',
236
- // 'performance',
215
+ 'gear-guide',
216
+ 'odd-times',
217
+ 'podcast',
218
+ 'spotlight',
219
+ 'performance',
237
220
  ]
238
221
  export const entertainmentLessonTypes = [
239
222
  'special',
@@ -251,9 +234,9 @@ export const lessonTypesMapping = {
251
234
  documentaries: ['documentary-lesson'],
252
235
  courses: ['course'],
253
236
  'guided courses': ['guided-course'],
254
- 'tiered courses': ['tiered-course'],
237
+ 'course collections': ['course-collection'],
255
238
  'skill packs': ['skill-pack'],
256
- specials: ['specials'],
239
+ specials: ['special'],
257
240
  shows: showsLessonTypes,
258
241
  collections: collectionLessonTypes,
259
242
  individuals: individualLessonsTypes,
@@ -611,30 +594,16 @@ export let contentTypeConfig = {
611
594
  // content with just the added 'instructors' Field
612
595
  'student-focus': contentWithInstructorsField,
613
596
  'quick-tips': contentWithInstructorsField,
614
- 'drum-fest-international-2022': contentWithInstructorsField,
615
597
  spotlight: contentWithInstructorsField,
616
- 'the-history-of-electronic-drums': contentWithInstructorsField,
617
- 'backstage-secret': contentWithInstructorsField,
618
598
  'question-and-answer': contentWithInstructorsField,
619
599
  'student-collaboration': contentWithInstructorsField,
620
600
  live: { ...contentWithInstructorsField, slug: 'live-streams' },
621
- solo: { ...contentWithInstructorsField, slug: 'solos' },
622
601
  'boot-camp': contentWithInstructorsField,
623
602
  'gear-guide': contentWithInstructorsField,
624
603
  performance: contentWithInstructorsField,
625
- challenges: contentWithInstructorsField,
626
- 'on-the-road': contentWithInstructorsField,
627
604
  // content with just the added 'sort' field
628
605
  podcast: contentWithSortField,
629
- 'in-rhythm': contentWithSortField,
630
- 'diy-drum-experiment': contentWithSortField,
631
- 'rhythmic-adventures-of-captain-carson': contentWithSortField,
632
606
  'study-the-greats': contentWithSortField,
633
- 'rhythms-from-another-planet': contentWithSortField,
634
- 'paiste-cymbals': contentWithInstructorsField,
635
- 'behind-the-scenes': contentWithSortField,
636
- 'exploring-beats': contentWithSortField,
637
- sonor: contentWithSortField,
638
607
  returning: {
639
608
  fields: [`quarter_published`, '"thumbnail": thumbnail.asset->url'],
640
609
  },
@@ -724,27 +693,12 @@ export function getNewReleasesTypes(brand) {
724
693
  case 'drumeo':
725
694
  return [
726
695
  ...baseNewTypes,
727
- 'drum-fest-international-2022',
728
696
  'spotlight',
729
- 'the-history-of-electronic-drums',
730
- 'backstage-secrets',
731
697
  'student-collaborations',
732
698
  'live',
733
- 'solos',
734
699
  'gear-guides',
735
700
  'performances',
736
- 'in-rhythm',
737
- 'challenges',
738
- 'on-the-road',
739
- 'diy-drum-experiments',
740
- 'rhythmic-adventures-of-captain-carson',
741
701
  'study-the-greats',
742
- 'rhythms-from-another-planet',
743
- 'tama-drums',
744
- 'paiste-cymbals',
745
- 'behind-the-scenes',
746
- 'exploring-beats',
747
- 'sonor',
748
702
  ]
749
703
  case 'guitareo':
750
704
  return [...baseNewTypes, 'archives', 'recording', 'chords-and-scales']
@@ -758,13 +712,12 @@ export function getNewReleasesTypes(brand) {
758
712
 
759
713
  export function getUpcomingEventsTypes(brand) {
760
714
  const baseLiveTypes = [
761
- 'student-review',
762
715
  'student-review',
763
716
  'student-focus',
764
717
  'coach-stream',
765
718
  'live',
766
719
  'question-and-answer',
767
- 'boot-camps',
720
+ 'boot-camp',
768
721
  'quick-tips',
769
722
  'recording',
770
723
  'pack-bundle-lesson',
@@ -773,28 +726,13 @@ export function getUpcomingEventsTypes(brand) {
773
726
  case 'drumeo':
774
727
  return [
775
728
  ...baseLiveTypes,
776
- 'drum-fest-international-2022',
777
729
  'spotlight',
778
- 'the-history-of-electronic-drums',
779
- 'backstage-secrets',
780
730
  'student-collaborations',
781
731
  'live',
782
- 'podcasts',
783
- 'solos',
784
- 'gear-guides',
785
- 'performances',
786
- 'in-rhythm',
787
- 'challenges',
788
- 'on-the-road',
789
- 'diy-drum-experiments',
790
- 'rhythmic-adventures-of-captain-carson',
732
+ 'podcast',
733
+ 'gear-guide',
734
+ 'performance',
791
735
  'study-the-greats',
792
- 'rhythms-from-another-planet',
793
- 'tama-drums',
794
- 'paiste-cymbals',
795
- 'behind-the-scenes',
796
- 'exploring-beats',
797
- 'sonor',
798
736
  ]
799
737
  case 'guitareo':
800
738
  return [...baseLiveTypes, 'archives']
package/src/index.d.ts CHANGED
@@ -216,23 +216,13 @@ import {
216
216
  createComment,
217
217
  deleteComment,
218
218
  editComment,
219
- fetchAllCompletedStates,
220
- fetchCarouselCardData,
221
219
  fetchComment,
222
220
  fetchCommentRelies,
223
221
  fetchComments,
224
- fetchCompletedContent,
225
- fetchCompletedState,
226
- fetchContentInProgress,
227
222
  fetchContentPageUserData,
228
- fetchLastInteractedChild,
229
223
  fetchLikeCount,
230
- fetchNextContentDataForParent,
231
224
  fetchRecentUserActivities,
232
- fetchSongsInProgress,
233
225
  fetchTopComment,
234
- fetchUserAward,
235
- fetchUserBadges,
236
226
  fetchUserPermissionsData,
237
227
  fetchUserPracticeMeta,
238
228
  fetchUserPracticeNotes,
@@ -486,7 +476,6 @@ declare module 'musora-content-services' {
486
476
  enrollUserInGuidedCourse,
487
477
  extractSanityUrl,
488
478
  fetchAll,
489
- fetchAllCompletedStates,
490
479
  fetchAllFilterOptions,
491
480
  fetchAllPacks,
492
481
  fetchArtistBySlug,
@@ -496,7 +485,6 @@ declare module 'musora-content-services' {
496
485
  fetchByRailContentId,
497
486
  fetchByRailContentIds,
498
487
  fetchByReference,
499
- fetchCarouselCardData,
500
488
  fetchCertificate,
501
489
  fetchChatAndLiveEnvent,
502
490
  fetchChatSettings,
@@ -506,9 +494,6 @@ declare module 'musora-content-services' {
506
494
  fetchCommentRelies,
507
495
  fetchComments,
508
496
  fetchCommunityGuidelines,
509
- fetchCompletedContent,
510
- fetchCompletedState,
511
- fetchContentInProgress,
512
497
  fetchContentPageUserData,
513
498
  fetchContentRows,
514
499
  fetchCustomerPayments,
@@ -523,7 +508,6 @@ declare module 'musora-content-services' {
523
508
  fetchInstructorLessons,
524
509
  fetchInstructors,
525
510
  fetchInterests,
526
- fetchLastInteractedChild,
527
511
  fetchLatestThreads,
528
512
  fetchLearningPathHierarchy,
529
513
  fetchLearningPathLessons,
@@ -540,7 +524,6 @@ declare module 'musora-content-services' {
540
524
  fetchMethodV2Structure,
541
525
  fetchMethodV2StructureFromId,
542
526
  fetchNewReleases,
543
- fetchNextContentDataForParent,
544
527
  fetchNotificationSettings,
545
528
  fetchNotifications,
546
529
  fetchOtherSongVersions,
@@ -569,7 +552,6 @@ declare module 'musora-content-services' {
569
552
  fetchSimilarItems,
570
553
  fetchSongArtistCount,
571
554
  fetchSongById,
572
- fetchSongsInProgress,
573
555
  fetchTabData,
574
556
  fetchThread,
575
557
  fetchThreads,
@@ -578,8 +560,6 @@ declare module 'musora-content-services' {
578
560
  fetchUninterests,
579
561
  fetchUnreadCount,
580
562
  fetchUpcomingEvents,
581
- fetchUserAward,
582
- fetchUserBadges,
583
563
  fetchUserPermissions,
584
564
  fetchUserPermissionsData,
585
565
  fetchUserPlaylists,
package/src/index.js CHANGED
@@ -220,23 +220,13 @@ import {
220
220
  createComment,
221
221
  deleteComment,
222
222
  editComment,
223
- fetchAllCompletedStates,
224
- fetchCarouselCardData,
225
223
  fetchComment,
226
224
  fetchCommentRelies,
227
225
  fetchComments,
228
- fetchCompletedContent,
229
- fetchCompletedState,
230
- fetchContentInProgress,
231
226
  fetchContentPageUserData,
232
- fetchLastInteractedChild,
233
227
  fetchLikeCount,
234
- fetchNextContentDataForParent,
235
228
  fetchRecentUserActivities,
236
- fetchSongsInProgress,
237
229
  fetchTopComment,
238
- fetchUserAward,
239
- fetchUserBadges,
240
230
  fetchUserPermissionsData,
241
231
  fetchUserPracticeMeta,
242
232
  fetchUserPracticeNotes,
@@ -485,7 +475,6 @@ export {
485
475
  enrollUserInGuidedCourse,
486
476
  extractSanityUrl,
487
477
  fetchAll,
488
- fetchAllCompletedStates,
489
478
  fetchAllFilterOptions,
490
479
  fetchAllPacks,
491
480
  fetchArtistBySlug,
@@ -495,7 +484,6 @@ export {
495
484
  fetchByRailContentId,
496
485
  fetchByRailContentIds,
497
486
  fetchByReference,
498
- fetchCarouselCardData,
499
487
  fetchCertificate,
500
488
  fetchChatAndLiveEnvent,
501
489
  fetchChatSettings,
@@ -505,9 +493,6 @@ export {
505
493
  fetchCommentRelies,
506
494
  fetchComments,
507
495
  fetchCommunityGuidelines,
508
- fetchCompletedContent,
509
- fetchCompletedState,
510
- fetchContentInProgress,
511
496
  fetchContentPageUserData,
512
497
  fetchContentRows,
513
498
  fetchCustomerPayments,
@@ -522,7 +507,6 @@ export {
522
507
  fetchInstructorLessons,
523
508
  fetchInstructors,
524
509
  fetchInterests,
525
- fetchLastInteractedChild,
526
510
  fetchLatestThreads,
527
511
  fetchLearningPathHierarchy,
528
512
  fetchLearningPathLessons,
@@ -539,7 +523,6 @@ export {
539
523
  fetchMethodV2Structure,
540
524
  fetchMethodV2StructureFromId,
541
525
  fetchNewReleases,
542
- fetchNextContentDataForParent,
543
526
  fetchNotificationSettings,
544
527
  fetchNotifications,
545
528
  fetchOtherSongVersions,
@@ -568,7 +551,6 @@ export {
568
551
  fetchSimilarItems,
569
552
  fetchSongArtistCount,
570
553
  fetchSongById,
571
- fetchSongsInProgress,
572
554
  fetchTabData,
573
555
  fetchThread,
574
556
  fetchThreads,
@@ -577,8 +559,6 @@ export {
577
559
  fetchUninterests,
578
560
  fetchUnreadCount,
579
561
  fetchUpcomingEvents,
580
- fetchUserAward,
581
- fetchUserBadges,
582
562
  fetchUserPermissions,
583
563
  fetchUserPermissionsData,
584
564
  fetchUserPlaylists,
@@ -128,7 +128,7 @@ export async function getTabResults(brand, pageName, tabName, {
128
128
 
129
129
 
130
130
  // Fetch metadata
131
- const metaData = await fetchMetadata(brand, pageName);
131
+ const metaData = await fetchMetadata(brand, pageName, { skipTabFiltering: true });
132
132
 
133
133
  // Process filters
134
134
  const filters = (metaData.filters ?? []).map(filter => ({
@@ -8,7 +8,7 @@ import {
8
8
  getResumeTimeSecondsByIdsAndCollections,
9
9
  } from './contentProgress'
10
10
  import { isContentLikedByIds } from './contentLikes'
11
- import { fetchLastInteractedChild, fetchLikeCount } from './railcontent'
11
+ import { fetchLikeCount } from './railcontent'
12
12
  import {COLLECTION_TYPE} from "./sync/models/ContentProgress";
13
13
 
14
14
  /**
@@ -73,7 +73,6 @@ export async function addContextToContent(dataPromise, ...dataArgs) {
73
73
  addProgressStatus = false,
74
74
  addProgressTimestamp = false,
75
75
  addResumeTimeSeconds = false,
76
- addLastInteractedChild = false,
77
76
  addNavigateTo = false,
78
77
  } = options
79
78
 
@@ -99,7 +98,6 @@ export async function addContextToContent(dataPromise, ...dataArgs) {
99
98
  ? getProgressDataByIds(ids, collection) : Promise.resolve(null),
100
99
  addIsLiked ? isContentLikedByIds(ids, collection) : Promise.resolve(null),
101
100
  addResumeTimeSeconds ? getResumeTimeSecondsByIds(ids, collection) : Promise.resolve(null),
102
- addLastInteractedChild ? fetchLastInteractedChild(ids, collection) : Promise.resolve(null),
103
101
  addNavigateTo ? getNavigateTo(items, collection) : Promise.resolve(null),
104
102
  ])
105
103
 
@@ -111,7 +109,6 @@ export async function addContextToContent(dataPromise, ...dataArgs) {
111
109
  ...(addIsLiked ? { isLiked: isLikedData?.[item.id] } : {}),
112
110
  ...(addLikeCount && ids.length === 1 ? { likeCount: await fetchLikeCount(item.id) } : {}),
113
111
  ...(addResumeTimeSeconds ? { resumeTime: resumeTimeData?.[item.id] } : {}),
114
- ...(addLastInteractedChild ? { lastInteractedChild: lastInteractedChildData?.[item.id] } : {}),
115
112
  ...(addNavigateTo ? { navigateTo: navigateToData?.[item.id] } : {}),
116
113
  })
117
114
 
@@ -11,97 +11,6 @@ import { GET, POST, PUT, DELETE } from '../infrastructure/http/HttpClient.ts'
11
11
  */
12
12
  const excludeFromGeneratedIndex = ['fetchUserPermissionsData']
13
13
 
14
- /**
15
- * Fetches the completion status of a specific lesson for the current user.
16
- *
17
- * @param {string} content_id - The ID of the lesson content to check.
18
- * @returns {Promise<Object|null>} - Returns the completion status object if found, otherwise null.
19
- * @example
20
- * fetchCurrentSongComplete('user123', 'lesson456', 'csrf-token')
21
- * .then(status => console.log(status))
22
- * .catch(error => console.error(error));
23
- */
24
- export async function fetchCompletedState(content_id) {
25
- const url = `/content/user_progress/${globalConfig.sessionConfig.userId}?content_ids[]=${content_id}`
26
- const result = await GET(url)
27
-
28
- if (result && result[content_id]) {
29
- return result[content_id]
30
- }
31
- return null
32
- }
33
-
34
- /**
35
- * Fetches the completion status for multiple songs for the current user.
36
- *
37
- * @param {Array<string>} contentIds - An array of content IDs to check.
38
- * @returns {Promise<Object|null>} - Returns an object containing completion statuses keyed by content ID, or null if an error occurs.
39
- * @example
40
- * fetchAllCompletedStates('user123', ['song456', 'song789'], 'csrf-token')
41
- * .then(statuses => console.log(statuses))
42
- * .catch(error => console.error(error));
43
- */
44
- export async function fetchAllCompletedStates(contentIds) {
45
- const url = `/content/user_progress/${globalConfig.sessionConfig.userId}?${contentIds.map((id) => `content_ids[]=${id}`).join('&')}`
46
- return await GET(url)
47
- }
48
-
49
- /**
50
- * Fetches a list of songs that are currently in progress for the current user.
51
- *
52
- * @param {string} brand - The brand associated with the songs.
53
- * @returns {Promise<Object|null>} - Returns an object containing in-progress songs if found, otherwise null.
54
- * @example
55
- * fetchSongsInProgress('drumeo')
56
- * .then(songs => console.log(songs))
57
- * .catch(error => console.error(error));
58
- */
59
- export async function fetchSongsInProgress(brand) {
60
- const url = `/content/in_progress/${globalConfig.sessionConfig.userId}?content_type=song&brand=${brand}`
61
- return await GET(url)
62
- }
63
-
64
- /**
65
- * Fetches a list of content that is currently in progress for the current user.
66
- *
67
- * @param {string} type - The content type associated with the content.
68
- * @param {string} brand - The brand associated with the content.
69
- * @param {number} [options.limit=20] - The limit of results per page.
70
- * @param {number} [options.page=1] - The page number for pagination.
71
- * @returns {Promise<Object|null>} - Returns an object containing in-progress content if found, otherwise null.
72
- * @example
73
- * fetchContentInProgress('song', 'drumeo')
74
- * .then(songs => console.log(songs))
75
- * .catch(error => console.error(error));
76
- */
77
- export async function fetchContentInProgress(type = 'all', brand, { page, limit } = {}) {
78
- const limitString = limit ? `&limit=${limit}` : ''
79
- const pageString = page ? `&page=${page}` : ''
80
- const contentTypeParam = type === 'all' ? '' : `content_type=${type}&`
81
- const url = `/content/in_progress/${globalConfig.sessionConfig.userId}?${contentTypeParam}brand=${brand}${limitString}${pageString}`
82
- return await GET(url)
83
- }
84
-
85
- /**
86
- * Fetches a list of content that has been completed for the current user.
87
- *
88
- * @param {string} type - The content type associated with the content.
89
- * @param {string} brand - The brand associated with the content.
90
- * @param {number} [options.limit=20] - The limit of results per page.
91
- * @param {number} [options.page=1] - The page number for pagination.
92
- * @returns {Promise<Object|null>} - Returns an object containing in-progress content if found, otherwise null.
93
- * @example
94
- * fetchCompletedContent('song', 'drumeo')
95
- * .then(songs => console.log(songs))
96
- * .catch(error => console.error(error));
97
- */
98
- export async function fetchCompletedContent(type = 'all', brand, { page, limit } = {}) {
99
- const limitString = limit ? `&limit=${limit}` : ''
100
- const pageString = page ? `&page=${page}` : ''
101
- const contentTypeParam = type === 'all' ? '' : `content_type=${type}&`
102
- const url = `/content/completed/${globalConfig.sessionConfig.userId}?${contentTypeParam}brand=${brand}${limitString}${pageString}`
103
- return await GET(url)
104
- }
105
14
 
106
15
  /**
107
16
  * Fetches user context data for a specific piece of content.
@@ -118,18 +27,6 @@ export async function fetchContentPageUserData(contentId) {
118
27
  return await GET(url)
119
28
  }
120
29
 
121
- /**
122
- * Fetches the ID and Type of the piece of content that would be the next one for the user
123
- *
124
- * @param {int} contentId - The id of the parent (method, level, or course) piece of content.
125
- * @returns {Promise<Object|null>} - Returns and Object with the id and type of the next piece of content if found, otherwise null.
126
- */
127
- export async function fetchNextContentDataForParent(contentId) {
128
- const url = `/content/${contentId}/next/${globalConfig.sessionConfig.userId}`
129
- const result = await GET(url)
130
- return result?.next ?? null
131
- }
132
-
133
30
  export async function fetchUserPermissionsData() {
134
31
  const url = `/content/user/permissions`
135
32
  return (await GET(url)) ?? []
@@ -145,40 +42,6 @@ export async function postPlaylistContentEngaged(playlistItemId) {
145
42
  return await POST(url, null)
146
43
  }
147
44
 
148
- /**
149
- * Fetch the user's best award for this challenge
150
- *
151
- * @param contentId - railcontent id of the challenge
152
- * @returns {Promise<any|null>} - streamed PDF
153
- */
154
- export async function fetchUserAward(contentId) {
155
- const url = `/challenges/download_award/${contentId}`
156
- return await GET(url)
157
- }
158
-
159
- /**
160
- * Fetch All Carousel Card Data
161
- *
162
- * @returns {Promise<any|null>}
163
- */
164
- export async function fetchCarouselCardData(brand = null) {
165
- const brandParam = brand ? `?brand=${brand}` : ''
166
- const url = `/api/v2/content/carousel${brandParam}`
167
- return await GET(url)
168
- }
169
-
170
- /**
171
- * Fetch all completed badges for the user ordered by completion date descending
172
- *
173
- * @param {string|null} brand -
174
- * @returns {Promise<any|null>}
175
- */
176
- export async function fetchUserBadges(brand = null) {
177
- const brandParam = brand ? `?brand=${brand}` : ''
178
- const url = `/challenges/user_badges/get${brandParam}`
179
- return await GET(url)
180
- }
181
-
182
45
  /**
183
46
  * Set a user's StudentView Flag
184
47
  *
@@ -473,32 +336,6 @@ export async function fetchUserPracticeNotes(date) {
473
336
  return await GET(url)
474
337
  }
475
338
 
476
- /**
477
- * Get the id and slug of last interacted child. Only valid for certain content types
478
- *
479
- * @async
480
- * @function fetchLastInteractedChild
481
- * @param {array} content_ids - Content ids of to get the last interacted child of
482
- *
483
- *
484
- * @returns {Promise<Object>} - keyed object per valid content ids with the child
485
- *
486
- * @example
487
- * try {
488
- * const response = await fetchLastInteractedChild([191369, 410427]);
489
- * console.log('child id', response[191369].content_id)
490
- * console.log('child slug', response[191369].slug)
491
- * } catch (error) {
492
- * console.error('Failed to get children', error);
493
- * }
494
- */
495
- export async function fetchLastInteractedChild(content_ids) {
496
- const params = new URLSearchParams()
497
- content_ids.forEach((id) => params.append('content_ids[]', id))
498
- const url = `/api/content/v1/user/last_interacted_child?${params.toString()}`
499
- return await GET(url)
500
- }
501
-
502
339
  /**
503
340
  * @typedef {Object} Activity
504
341
  * @property {string} id - Unique identifier for the activity.