musora-content-services 2.108.0 → 2.111.0
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.
- package/CHANGELOG.md +29 -0
- package/CLAUDE.md +2 -2
- package/package.json +1 -1
- package/src/contentMetaData.js +0 -5
- package/src/contentTypeConfig.js +11 -73
- package/src/index.d.ts +0 -20
- package/src/index.js +0 -20
- package/src/services/content.js +1 -1
- package/src/services/contentAggregator.js +1 -4
- package/src/services/railcontent.js +0 -163
- package/src/services/sanity.js +258 -7
- package/src/services/sync/adapters/factory.ts +6 -6
- package/src/services/sync/adapters/lokijs.ts +174 -1
- package/src/services/sync/context/providers/durability.ts +1 -0
- package/src/services/sync/database/factory.ts +12 -5
- package/src/services/sync/effects/index.ts +6 -0
- package/src/services/sync/effects/logout-warning.ts +47 -0
- package/src/services/sync/errors/boundary.ts +4 -6
- package/src/services/sync/errors/index.ts +16 -0
- package/src/services/sync/fetch.ts +5 -5
- package/src/services/sync/manager.ts +80 -40
- package/src/services/sync/repositories/base.ts +1 -8
- package/src/services/sync/retry.ts +4 -4
- package/src/services/sync/store/index.ts +34 -31
- package/src/services/sync/store/push-coalescer.ts +3 -3
- package/src/services/sync/store-configs.ts +10 -8
- package/src/services/sync/telemetry/flood-prevention.ts +27 -0
- package/src/services/sync/telemetry/index.ts +71 -9
- package/src/services/sync/telemetry/sampling.ts +2 -6
- package/src/services/user/types.d.ts +0 -7
- package/test/sync/adapter.ts +2 -34
- package/test/sync/initialize-sync-manager.js +8 -25
- package/.claude/settings.local.json +0 -9
- package/src/services/sync/concurrency-safety.ts +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
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.111.0](https://github.com/railroadmedia/musora-content-services/compare/v2.110.3...v2.111.0) (2026-01-05)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **MU2-1323:** Add dynamic filtering to lessons/songs excluding those without avaialable content ([072a471](https://github.com/railroadmedia/musora-content-services/commit/072a471a8b37bb31fc1421375563be0b2f124beb))
|
|
11
|
+
* **MU2-1323:** Remove redundant constant ([768befd](https://github.com/railroadmedia/musora-content-services/commit/768befdf393723cb0e091605f3c7e6ef4d523a92))
|
|
12
|
+
* **MU2-1323:** Use filterTypes for get all content types ([8065100](https://github.com/railroadmedia/musora-content-services/commit/80651009fcc9dae6661b3cbaecf55d5c3585d044))
|
|
13
|
+
|
|
14
|
+
### [2.110.3](https://github.com/railroadmedia/musora-content-services/compare/v2.110.2...v2.110.3) (2026-01-05)
|
|
15
|
+
|
|
16
|
+
### [2.110.2](https://github.com/railroadmedia/musora-content-services/compare/v2.110.1...v2.110.2) (2026-01-05)
|
|
17
|
+
|
|
18
|
+
### [2.110.1](https://github.com/railroadmedia/musora-content-services/compare/v2.110.0...v2.110.1) (2026-01-05)
|
|
19
|
+
|
|
20
|
+
## [2.110.0](https://github.com/railroadmedia/musora-content-services/compare/v2.109.0...v2.110.0) (2026-01-05)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* **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))
|
|
26
|
+
|
|
27
|
+
## [2.109.0](https://github.com/railroadmedia/musora-content-services/compare/v2.108.0...v2.109.0) (2026-01-05)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Features
|
|
31
|
+
|
|
32
|
+
* **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))
|
|
33
|
+
|
|
5
34
|
## [2.108.0](https://github.com/railroadmedia/musora-content-services/compare/v2.107.8...v2.108.0) (2026-01-02)
|
|
6
35
|
|
|
7
36
|
|
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.
|
|
333
|
-
|
|
332
|
+
manager.registerStrategies(
|
|
333
|
+
ContentLike, ContentProgress, Practice, PracticeDayNote],
|
|
334
334
|
[initialStrategy, onlineStrategy, activityStrategy, hourlyPollingStrategy]
|
|
335
335
|
)
|
|
336
336
|
```
|
package/package.json
CHANGED
package/src/contentMetaData.js
CHANGED
|
@@ -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]
|
package/src/contentTypeConfig.js
CHANGED
|
@@ -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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
-
'
|
|
237
|
+
'course collections': ['course-collection'],
|
|
255
238
|
'skill packs': ['skill-pack'],
|
|
256
|
-
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-
|
|
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
|
-
'
|
|
783
|
-
'
|
|
784
|
-
'
|
|
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,
|
package/src/services/content.js
CHANGED
|
@@ -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 {
|
|
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.
|