musora-content-services 2.107.8 → 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 (38) hide show
  1. package/CHANGELOG.md +32 -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 +13 -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/contentProgress.js +13 -8
  11. package/src/services/railcontent.js +0 -163
  12. package/src/services/sanity.js +258 -7
  13. package/src/services/sync/adapters/factory.ts +6 -6
  14. package/src/services/sync/adapters/lokijs.ts +174 -1
  15. package/src/services/sync/context/providers/durability.ts +1 -0
  16. package/src/services/sync/database/factory.ts +12 -5
  17. package/src/services/sync/effects/index.ts +6 -0
  18. package/src/services/sync/effects/logout-warning.ts +47 -0
  19. package/src/services/sync/errors/boundary.ts +4 -6
  20. package/src/services/sync/errors/index.ts +16 -0
  21. package/src/services/sync/fetch.ts +5 -5
  22. package/src/services/sync/manager.ts +80 -40
  23. package/src/services/sync/models/ContentProgress.ts +6 -0
  24. package/src/services/sync/repositories/base.ts +1 -8
  25. package/src/services/sync/repositories/content-progress.ts +8 -2
  26. package/src/services/sync/retry.ts +4 -4
  27. package/src/services/sync/schema/index.ts +1 -0
  28. package/src/services/sync/store/index.ts +34 -31
  29. package/src/services/sync/store/push-coalescer.ts +3 -3
  30. package/src/services/sync/store-configs.ts +10 -8
  31. package/src/services/sync/telemetry/flood-prevention.ts +27 -0
  32. package/src/services/sync/telemetry/index.ts +71 -9
  33. package/src/services/sync/telemetry/sampling.ts +2 -6
  34. package/src/services/user/types.d.ts +0 -7
  35. package/test/sync/adapter.ts +2 -34
  36. package/test/sync/initialize-sync-manager.js +8 -25
  37. package/.claude/settings.local.json +0 -9
  38. package/src/services/sync/concurrency-safety.ts +0 -4
package/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
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
+
25
+ ## [2.108.0](https://github.com/railroadmedia/musora-content-services/compare/v2.107.8...v2.108.0) (2026-01-02)
26
+
27
+
28
+ ### Features
29
+
30
+ * adds column and implements for hiding cards ([#679](https://github.com/railroadmedia/musora-content-services/issues/679)) ([35ac42c](https://github.com/railroadmedia/musora-content-services/commit/35ac42cebe397c557d0b197d4fab38907ca08ab7))
31
+
32
+
33
+ ### Bug Fixes
34
+
35
+ * some fixes from Rob ([#676](https://github.com/railroadmedia/musora-content-services/issues/676)) ([7e068ee](https://github.com/railroadmedia/musora-content-services/commit/7e068eee3cabc4de1d0620fe58eadf138532ab56))
36
+
5
37
  ### [2.107.8](https://github.com/railroadmedia/musora-content-services/compare/v2.107.7...v2.107.8) (2025-12-30)
6
38
 
7
39
 
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.107.8",
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,
@@ -301,6 +284,7 @@ export const progressTypesMapping = {
301
284
  'guided course': ['guided-course'],
302
285
  pack: ['pack', 'semester-pack'],
303
286
  'learning path': ['learning-path-v2'],
287
+ 'skill pack': skillLessonTypes,
304
288
  'jam track': jamTrackLessonTypes,
305
289
  'course video': ['course-lesson'],
306
290
  }
@@ -343,6 +327,7 @@ export const recentTypes = {
343
327
  home: [
344
328
  ...individualLessonsTypes,
345
329
  ...tutorialsLessonTypes,
330
+ ...skillLessonTypes,
346
331
  ...transcriptionsLessonTypes,
347
332
  ...playAlongLessonTypes,
348
333
  'guided-course',
@@ -609,30 +594,16 @@ export let contentTypeConfig = {
609
594
  // content with just the added 'instructors' Field
610
595
  'student-focus': contentWithInstructorsField,
611
596
  'quick-tips': contentWithInstructorsField,
612
- 'drum-fest-international-2022': contentWithInstructorsField,
613
597
  spotlight: contentWithInstructorsField,
614
- 'the-history-of-electronic-drums': contentWithInstructorsField,
615
- 'backstage-secret': contentWithInstructorsField,
616
598
  'question-and-answer': contentWithInstructorsField,
617
599
  'student-collaboration': contentWithInstructorsField,
618
600
  live: { ...contentWithInstructorsField, slug: 'live-streams' },
619
- solo: { ...contentWithInstructorsField, slug: 'solos' },
620
601
  'boot-camp': contentWithInstructorsField,
621
602
  'gear-guide': contentWithInstructorsField,
622
603
  performance: contentWithInstructorsField,
623
- challenges: contentWithInstructorsField,
624
- 'on-the-road': contentWithInstructorsField,
625
604
  // content with just the added 'sort' field
626
605
  podcast: contentWithSortField,
627
- 'in-rhythm': contentWithSortField,
628
- 'diy-drum-experiment': contentWithSortField,
629
- 'rhythmic-adventures-of-captain-carson': contentWithSortField,
630
606
  'study-the-greats': contentWithSortField,
631
- 'rhythms-from-another-planet': contentWithSortField,
632
- 'paiste-cymbals': contentWithInstructorsField,
633
- 'behind-the-scenes': contentWithSortField,
634
- 'exploring-beats': contentWithSortField,
635
- sonor: contentWithSortField,
636
607
  returning: {
637
608
  fields: [`quarter_published`, '"thumbnail": thumbnail.asset->url'],
638
609
  },
@@ -722,27 +693,12 @@ export function getNewReleasesTypes(brand) {
722
693
  case 'drumeo':
723
694
  return [
724
695
  ...baseNewTypes,
725
- 'drum-fest-international-2022',
726
696
  'spotlight',
727
- 'the-history-of-electronic-drums',
728
- 'backstage-secrets',
729
697
  'student-collaborations',
730
698
  'live',
731
- 'solos',
732
699
  'gear-guides',
733
700
  'performances',
734
- 'in-rhythm',
735
- 'challenges',
736
- 'on-the-road',
737
- 'diy-drum-experiments',
738
- 'rhythmic-adventures-of-captain-carson',
739
701
  'study-the-greats',
740
- 'rhythms-from-another-planet',
741
- 'tama-drums',
742
- 'paiste-cymbals',
743
- 'behind-the-scenes',
744
- 'exploring-beats',
745
- 'sonor',
746
702
  ]
747
703
  case 'guitareo':
748
704
  return [...baseNewTypes, 'archives', 'recording', 'chords-and-scales']
@@ -756,13 +712,12 @@ export function getNewReleasesTypes(brand) {
756
712
 
757
713
  export function getUpcomingEventsTypes(brand) {
758
714
  const baseLiveTypes = [
759
- 'student-review',
760
715
  'student-review',
761
716
  'student-focus',
762
717
  'coach-stream',
763
718
  'live',
764
719
  'question-and-answer',
765
- 'boot-camps',
720
+ 'boot-camp',
766
721
  'quick-tips',
767
722
  'recording',
768
723
  'pack-bundle-lesson',
@@ -771,28 +726,13 @@ export function getUpcomingEventsTypes(brand) {
771
726
  case 'drumeo':
772
727
  return [
773
728
  ...baseLiveTypes,
774
- 'drum-fest-international-2022',
775
729
  'spotlight',
776
- 'the-history-of-electronic-drums',
777
- 'backstage-secrets',
778
730
  'student-collaborations',
779
731
  'live',
780
- 'podcasts',
781
- 'solos',
782
- 'gear-guides',
783
- 'performances',
784
- 'in-rhythm',
785
- 'challenges',
786
- 'on-the-road',
787
- 'diy-drum-experiments',
788
- 'rhythmic-adventures-of-captain-carson',
732
+ 'podcast',
733
+ 'gear-guide',
734
+ 'performance',
789
735
  'study-the-greats',
790
- 'rhythms-from-another-planet',
791
- 'tama-drums',
792
- 'paiste-cymbals',
793
- 'behind-the-scenes',
794
- 'exploring-beats',
795
- 'sonor',
796
736
  ]
797
737
  case 'guitareo':
798
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
 
@@ -467,13 +467,14 @@ export async function contentStatusReset(contentId, collection = null, {skipPush
467
467
  return resetStatus(contentId, collection, {skipPush})
468
468
  }
469
469
 
470
- async function saveContentProgress(contentId, collection, progress, currentSeconds, {skipPush = false} = {}) {
470
+ async function saveContentProgress(contentId, collection, progress, currentSeconds, {skipPush = false, hideFromProgressRow = false} = {}) {
471
471
  const isLP = collection?.type === COLLECTION_TYPE.LEARNING_PATH
472
472
 
473
473
  // filter out contentIds that are setting progress lower than existing
474
474
  const contentIdProgress = await getProgressDataByIds([contentId], collection)
475
- if (progress <= contentIdProgress[contentId].progress) {
476
- return
475
+ const currentProgress = contentIdProgress[contentId].progress;
476
+ if (progress <= currentProgress) {
477
+ progress = currentProgress;
477
478
  }
478
479
 
479
480
  const response = await db.contentProgress.recordProgress(
@@ -481,11 +482,15 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
481
482
  collection,
482
483
  progress,
483
484
  currentSeconds,
484
- {skipPush: true}
485
+ {skipPush: true, hideFromProgressRow}
485
486
  )
486
487
  // note - previous implementation explicitly did not trickle progress to children here
487
488
  // (only to siblings/parents via le bubbles)
488
489
 
490
+ if (progress === currentProgress) {
491
+ return
492
+ }
493
+
489
494
  const hierarchy = await getHierarchy(contentId, collection)
490
495
 
491
496
  const bubbledProgresses = await bubbleProgress(hierarchy, contentId, collection)
@@ -499,7 +504,7 @@ async function saveContentProgress(contentId, collection, progress, currentSecon
499
504
  }
500
505
 
501
506
  // BE bubbling/trickling currently does not work, so we utilize non-tentative pushing when learning path collection
502
- await db.contentProgress.recordProgressMany(bubbledProgresses, collection, {tentative: !isLP, skipPush: true})
507
+ await db.contentProgress.recordProgressMany(bubbledProgresses, collection, {tentative: !isLP, skipPush: true, hideFromProgressRow})
503
508
 
504
509
  if (isLP) {
505
510
  let exportIds = bubbledProgresses
@@ -577,11 +582,11 @@ async function duplicateLearningPathProgressToExternalContents(ids, collection,
577
582
  // each handles its own bubbling.
578
583
  // skipPush on all but last to avoid multiple push requests
579
584
  filteredIds.forEach(([id, pct], index) => {
585
+ let skip = true
580
586
  if (index === filteredIds.length - 1) {
581
- saveContentProgress(parseInt(id), null, pct, null, {skipPush})
582
- } else {
583
- saveContentProgress(parseInt(id), null, pct, null, {skipPush: true})
587
+ skip = skipPush
584
588
  }
589
+ saveContentProgress(parseInt(id), null, pct, null, {skipPush: skip, hideFromProgressRow: true})
585
590
  })
586
591
  }
587
592