musora-content-services 2.96.0 → 2.96.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
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.96.2](https://github.com/railroadmedia/musora-content-services/compare/v2.96.1...v2.96.2) (2025-12-09)
6
+
7
+ ### [2.96.1](https://github.com/railroadmedia/musora-content-services/compare/v2.96.0...v2.96.1) (2025-12-09)
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * **agi:** interface return types ([cc0cfae](https://github.com/railroadmedia/musora-content-services/commit/cc0cfae1282266567ac46a6eb072f76ffde7032e))
13
+
5
14
  ## [2.96.0](https://github.com/railroadmedia/musora-content-services/compare/v2.95.5...v2.96.0) (2025-12-09)
6
15
 
7
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.96.0",
3
+ "version": "2.96.2",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.d.ts CHANGED
@@ -267,7 +267,6 @@ import {
267
267
  fetchComingSoon,
268
268
  fetchCommentModContentData,
269
269
  fetchContentRows,
270
- fetchFoundation,
271
270
  fetchHierarchy,
272
271
  fetchLearningPathHierarchy,
273
272
  fetchLeaving,
@@ -275,15 +274,10 @@ import {
275
274
  fetchLessonsFeaturingThisContent,
276
275
  fetchLiveEvent,
277
276
  fetchMetadata,
278
- fetchMethod,
279
- fetchMethodChildren,
280
- fetchMethodChildrenIds,
281
- fetchMethodPreviousNextLesson,
282
277
  fetchMethodV2IntroVideo,
283
278
  fetchMethodV2Structure,
284
279
  fetchMethodV2StructureFromId,
285
280
  fetchNewReleases,
286
- fetchNextPreviousLesson,
287
281
  fetchOtherSongVersions,
288
282
  fetchOwnedContent,
289
283
  fetchPackAll,
@@ -504,7 +498,6 @@ declare module 'musora-content-services' {
504
498
  fetchEnrollmentPageMetadata,
505
499
  fetchFollowedThreads,
506
500
  fetchForumCategories,
507
- fetchFoundation,
508
501
  fetchGenreBySlug,
509
502
  fetchGenreLessons,
510
503
  fetchGenres,
@@ -527,16 +520,11 @@ declare module 'musora-content-services' {
527
520
  fetchLiveEventPollingState,
528
521
  fetchMemberships,
529
522
  fetchMetadata,
530
- fetchMethod,
531
- fetchMethodChildren,
532
- fetchMethodChildrenIds,
533
- fetchMethodPreviousNextLesson,
534
523
  fetchMethodV2IntroVideo,
535
524
  fetchMethodV2Structure,
536
525
  fetchMethodV2StructureFromId,
537
526
  fetchNewReleases,
538
527
  fetchNextContentDataForParent,
539
- fetchNextPreviousLesson,
540
528
  fetchNotificationSettings,
541
529
  fetchNotifications,
542
530
  fetchOtherSongVersions,
package/src/index.js CHANGED
@@ -271,7 +271,6 @@ import {
271
271
  fetchComingSoon,
272
272
  fetchCommentModContentData,
273
273
  fetchContentRows,
274
- fetchFoundation,
275
274
  fetchHierarchy,
276
275
  fetchLearningPathHierarchy,
277
276
  fetchLeaving,
@@ -279,15 +278,10 @@ import {
279
278
  fetchLessonsFeaturingThisContent,
280
279
  fetchLiveEvent,
281
280
  fetchMetadata,
282
- fetchMethod,
283
- fetchMethodChildren,
284
- fetchMethodChildrenIds,
285
- fetchMethodPreviousNextLesson,
286
281
  fetchMethodV2IntroVideo,
287
282
  fetchMethodV2Structure,
288
283
  fetchMethodV2StructureFromId,
289
284
  fetchNewReleases,
290
- fetchNextPreviousLesson,
291
285
  fetchOtherSongVersions,
292
286
  fetchOwnedContent,
293
287
  fetchPackAll,
@@ -503,7 +497,6 @@ export {
503
497
  fetchEnrollmentPageMetadata,
504
498
  fetchFollowedThreads,
505
499
  fetchForumCategories,
506
- fetchFoundation,
507
500
  fetchGenreBySlug,
508
501
  fetchGenreLessons,
509
502
  fetchGenres,
@@ -526,16 +519,11 @@ export {
526
519
  fetchLiveEventPollingState,
527
520
  fetchMemberships,
528
521
  fetchMetadata,
529
- fetchMethod,
530
- fetchMethodChildren,
531
- fetchMethodChildrenIds,
532
- fetchMethodPreviousNextLesson,
533
522
  fetchMethodV2IntroVideo,
534
523
  fetchMethodV2Structure,
535
524
  fetchMethodV2StructureFromId,
536
525
  fetchNewReleases,
537
526
  fetchNextContentDataForParent,
538
- fetchNextPreviousLesson,
539
527
  fetchNotificationSettings,
540
528
  fetchNotifications,
541
529
  fetchOtherSongVersions,
@@ -15,6 +15,11 @@ export interface Artist {
15
15
  lessonCount: number
16
16
  }
17
17
 
18
+ export interface Artists {
19
+ data: Artist[]
20
+ total: number
21
+ }
22
+
18
23
  /**
19
24
  * Fetch all artists with lessons available for a specific brand.
20
25
  *
@@ -29,7 +34,7 @@ export interface Artist {
29
34
  export async function fetchArtists(
30
35
  brand: Brands | string,
31
36
  options: BuildQueryOptions = { sort: 'lower(name) asc' }
32
- ): Promise<Artist[] | null> {
37
+ ): Promise<Artists> {
33
38
  const lessonFilter = await new FilterBuilder(`brand == "${brand}" && references(^._id)`, {
34
39
  bypassPermissions: true,
35
40
  }).buildFilter()
@@ -15,6 +15,11 @@ export interface Genre {
15
15
  thumbnail: string
16
16
  }
17
17
 
18
+ export interface Genres {
19
+ data: Genre[]
20
+ total: number
21
+ }
22
+
18
23
  /**
19
24
  * Fetch all genres with lessons available for a specific brand.
20
25
  *
@@ -29,7 +34,7 @@ export interface Genre {
29
34
  export async function fetchGenres(
30
35
  brand: Brands | string,
31
36
  options: BuildQueryOptions = { sort: 'lower(name) asc' }
32
- ): Promise<Genre[]> {
37
+ ): Promise<Genres> {
33
38
  const lessonFilter = await new FilterBuilder(`brand == "${brand}" && references(^._id)`, {
34
39
  bypassPermissions: true,
35
40
  }).buildFilter()
@@ -35,7 +35,7 @@ export interface Instructors {
35
35
  export async function fetchInstructors(
36
36
  brand: Brands | string,
37
37
  options: BuildQueryOptions
38
- ): Promise<Instructor[]> {
38
+ ): Promise<Instructors> {
39
39
  const lessonFilter = await new FilterBuilder(`brand == "${brand}" && references(^._id)`, {
40
40
  bypassPermissions: true,
41
41
  }).buildFilter()
@@ -866,206 +866,6 @@ export async function fetchAllFilterOptions(
866
866
  return includeTabs ? { ...results, tabs, catalogName } : results
867
867
  }
868
868
 
869
- //Daniel Nov 14 2025 note - keeping this for when we migrate foundations to packs, so we know what fields to use.
870
- /**
871
- * Fetch the Foundations 2019.
872
- * @param {string} slug - The slug of the method.
873
- * @returns {Promise<Object|null>} - The fetched foundation data or null if not found.
874
- */
875
- export async function fetchFoundation(slug) {
876
- const filterParams = {}
877
- const query = await buildQuery(
878
- `_type == 'foundation' && slug.current == "${slug}"`,
879
- filterParams,
880
- getFieldsForContentType('foundation'),
881
- {
882
- sortOrder: 'published_on asc',
883
- isSingle: true,
884
- }
885
- )
886
- return fetchSanity(query, false)
887
- }
888
-
889
- /**
890
- * Fetch the Method (learning-paths) for a specific brand.
891
- * @param {string} brand - The brand for which to fetch methods.
892
- * @param {string} slug - The slug of the method.
893
- * @returns {Promise<Object|null>} - The fetched methods data or null if not found.
894
- */
895
- //todo BEH-1446 depreciated. remove all old method functions
896
- export async function fetchMethod(brand, slug) {
897
- const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
898
-
899
- const query = `*[_type == 'learning-path' && brand == "${brand}" && slug.current == "${slug}"] {
900
- "description": ${descriptionField},
901
- "instructors":instructor[]->name,
902
- published_on,
903
- "id": railcontent_id,
904
- railcontent_id,
905
- "slug": slug.current,
906
- status,
907
- title,
908
- video,
909
- length_in_seconds,
910
- parent_content_data,
911
- "breadcrumbs_data": parent_content_data[] {
912
- "id": id,
913
- "title": *[railcontent_id == ^.id][0].title,
914
- "url": *[railcontent_id == ^.id][0].web_url_path
915
- } | order(length(url)),
916
- "type": _type,
917
- "permission_id": permission_v2,
918
- "levels": child[${childrenFilter}]->
919
- {
920
- "id": railcontent_id,
921
- published_on,
922
- child_count,
923
- difficulty,
924
- difficulty_string,
925
- "thumbnail": thumbnail.asset->url,
926
- "instructor": instructor[]->{name},
927
- title,
928
- "type": _type,
929
- "description": ${descriptionField},
930
- "url": web_url_path,
931
- web_url_path,
932
- xp,
933
- total_xp
934
- }
935
- } | order(published_on asc)`
936
- return fetchSanity(query, false)
937
- }
938
-
939
- /**
940
- * Fetch the child courses for a specific method by Railcontent ID.
941
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
942
- * @returns {Promise<Object|null>} - The fetched next lesson data or null if not found.
943
- */
944
- export async function fetchMethodChildren(railcontentId) {
945
- const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
946
-
947
- const query = `*[railcontent_id == ${railcontentId}]{
948
- "child_count":coalesce(count(child[${childrenFilter}]->), 0),
949
- "id": railcontent_id,
950
- "description": ${descriptionField},
951
- "thumbnail": thumbnail.asset->url,
952
- title,
953
- xp,
954
- total_xp,
955
- parent_content_data,
956
- "resources": ${resourcesField},
957
- "breadcrumbs_data": parent_content_data[] {
958
- "id": id,
959
- "title": *[railcontent_id == ^.id][0].title,
960
- "url": *[railcontent_id == ^.id][0].web_url_path
961
- } | order(length(url)),
962
- 'children': child[(${childrenFilter})]->{
963
- ${getFieldsForContentType('method')}
964
- },
965
- }[0..1]`
966
- return fetchSanity(query, true)
967
- }
968
-
969
- /**
970
- * Fetch the next lesson for a specific method by Railcontent ID.
971
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
972
- * @param {string} methodId - The RailcontentID of the method
973
- * @returns {Promise<Object|null>} - object with `nextLesson` and `previousLesson` attributes
974
- * @example
975
- * fetchMethodPreviousNextLesson(241284, 241247)
976
- * .then(data => { console.log('nextLesson', data.nextLesson); console.log('prevlesson', data.prevLesson);})
977
- * .catch(error => console.error(error));
978
- */
979
- export async function fetchMethodPreviousNextLesson(railcontentId, methodId) {
980
- const sortedChildren = await fetchMethodChildrenIds(methodId)
981
- const index = sortedChildren.indexOf(Number(railcontentId))
982
- let nextId = sortedChildren[index + 1]
983
- let previousId = sortedChildren[index - 1]
984
- let ids = []
985
- if (nextId) ids.push(nextId)
986
- if (previousId) ids.push(previousId)
987
- let nextPrev = await fetchByRailContentIds(ids)
988
- const nextLesson = nextPrev.find((elem) => {
989
- return elem['id'] === nextId
990
- })
991
- const prevLesson = nextPrev.find((elem) => {
992
- return elem['id'] === previousId
993
- })
994
- return { nextLesson, prevLesson }
995
- }
996
-
997
- /**
998
- * Fetch all children of a specific method by Railcontent ID.
999
- * @param {string} railcontentId - The Railcontent ID of the method.
1000
- * @returns {Promise<Array<Object>|null>} - The fetched children data or null if not found.
1001
- */
1002
- export async function fetchMethodChildrenIds(railcontentId) {
1003
- const childrenFilter = await new FilterBuilder(``, { isChildrenFilter: true }).buildFilter()
1004
-
1005
- const query = `*[ railcontent_id == ${railcontentId}]{
1006
- 'children': child[${childrenFilter}]-> {
1007
- 'id': railcontent_id,
1008
- 'type' : _type,
1009
- 'children': child[${childrenFilter}]-> {
1010
- 'id': railcontent_id,
1011
- 'type' : _type,
1012
- 'children': child[${childrenFilter}]-> {
1013
- 'id': railcontent_id,
1014
- 'type' : _type,
1015
- }
1016
- }
1017
- }
1018
- }`
1019
- let allChildren = await fetchSanity(query, false)
1020
- return getChildrenToDepth(allChildren, 4)
1021
- }
1022
-
1023
- function getChildrenToDepth(parent, depth = 1) {
1024
- let allChildrenIds = []
1025
- if (parent && parent['children'] && depth > 0) {
1026
- parent['children'].forEach((child) => {
1027
- if (!child['children']) {
1028
- allChildrenIds.push(child['id'])
1029
- }
1030
- allChildrenIds = allChildrenIds.concat(getChildrenToDepth(child, depth - 1))
1031
- })
1032
- }
1033
- return allChildrenIds
1034
- }
1035
-
1036
- /**
1037
- * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
1038
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
1039
- * @returns {Promise<Object|null>} - The fetched next and previous lesson data or null if found.
1040
- */
1041
- export async function fetchNextPreviousLesson(railcontentId) {
1042
- const document = await fetchLessonContent(railcontentId)
1043
- if (document.parent_content_data && document.parent_content_data.length > 0) {
1044
- const lastElement = document.parent_content_data[document.parent_content_data.length - 1]
1045
- const results = await fetchMethodPreviousNextLesson(railcontentId, lastElement.id)
1046
- return results
1047
- }
1048
- const processedData = processMetadata(document.brand, document.type, true)
1049
- let sortBy = processedData?.sortBy ?? 'published_on'
1050
- const isDesc = sortBy.startsWith('-')
1051
- sortBy = isDesc ? sortBy.substring(1) : sortBy
1052
- let sortValue = document[sortBy]
1053
- if (sortValue == null) {
1054
- sortBy = 'railcontent_id'
1055
- sortValue = document['railcontent_id']
1056
- }
1057
- const isNumeric = !isNaN(sortValue)
1058
- let prevComparison = isNumeric ? `${sortBy} <= ${sortValue}` : `${sortBy} <= "${sortValue}"`
1059
- let nextComparison = isNumeric ? `${sortBy} >= ${sortValue}` : `${sortBy} >= "${sortValue}"`
1060
- const fields = getFieldsForContentType(document.type)
1061
- const query = `{
1062
- "prevLesson": *[brand == "${document.brand}" && status == "${document.status}" && _type == "${document.type}" && ${prevComparison} && railcontent_id != ${railcontentId}] | order(${sortBy} desc){${fields}}[0...1][0],
1063
- "nextLesson": *[brand == "${document.brand}" && status == "${document.status}" && _type == "${document.type}" && ${nextComparison} && railcontent_id != ${railcontentId}] | order(${sortBy} asc){${fields}}[0...1][0]
1064
- }`
1065
-
1066
- return await fetchSanity(query, true)
1067
- }
1068
-
1069
869
  /**
1070
870
  * Fetch the next piece of content under a parent by Railcontent ID
1071
871
  * @param {int} railcontentId - The Railcontent ID of the parent content
@@ -308,12 +308,7 @@ function serializeIds(ids: { id: RecordId }): { client_record_id: RecordId } {
308
308
 
309
309
  function deserializeRecord(record: SyncSyncable<BaseModel, 'client_record_id'> | null): SyncSyncable<BaseModel, 'id'> | null {
310
310
  if (record) {
311
- const { client_record_id: id, ...rest } = record as any
312
-
313
- if ('collection_type' in rest && rest.collection_type === 'self') {
314
- rest.collection_type = null
315
- rest.collection_id = null
316
- }
311
+ const { client_record_id: id, ...rest } = record
317
312
 
318
313
  return {
319
314
  ...rest,
@@ -2,9 +2,12 @@ import BaseModel from './Base'
2
2
  import { SYNC_TABLES } from '../schema'
3
3
 
4
4
  export enum COLLECTION_TYPE {
5
+ SELF = 'self',
6
+ GUIDED_COURSE = 'guided-course',
5
7
  LEARNING_PATH = 'learning-path-v2',
6
8
  PLAYLIST = 'playlist',
7
9
  }
10
+ export const COLLECTION_ID_SELF = 0
8
11
 
9
12
  export enum STATE {
10
13
  STARTED = 'started',
@@ -13,8 +16,8 @@ export enum STATE {
13
16
 
14
17
  export default class ContentProgress extends BaseModel<{
15
18
  content_id: number
16
- collection_type: COLLECTION_TYPE | null
17
- collection_id: number | null
19
+ collection_type: COLLECTION_TYPE
20
+ collection_id: number
18
21
  state: STATE
19
22
  progress_percent: number
20
23
  resume_time_seconds: number | null
@@ -34,10 +37,10 @@ export default class ContentProgress extends BaseModel<{
34
37
  return this._getRaw('progress_percent') as number
35
38
  }
36
39
  get collection_type() {
37
- return (this._getRaw('collection_type') as COLLECTION_TYPE) || null
40
+ return this._getRaw('collection_type') as COLLECTION_TYPE
38
41
  }
39
42
  get collection_id() {
40
- return (this._getRaw('collection_id') as number) || null
43
+ return this._getRaw('collection_id') as number
41
44
  }
42
45
  get resume_time_seconds() {
43
46
  return (this._getRaw('resume_time_seconds') as number) || null
@@ -55,10 +58,10 @@ export default class ContentProgress extends BaseModel<{
55
58
  set progress_percent(value: number) {
56
59
  this._setRaw('progress_percent', Math.min(100, Math.max(0, value)))
57
60
  }
58
- set collection_type(value: COLLECTION_TYPE | null) {
61
+ set collection_type(value: COLLECTION_TYPE) {
59
62
  this._setRaw('collection_type', value)
60
63
  }
61
- set collection_id(value: number | null) {
64
+ set collection_id(value: number) {
62
65
  this._setRaw('collection_id', value)
63
66
  }
64
67
  set resume_time_seconds(value: number | null) {
@@ -1,12 +1,12 @@
1
1
  import SyncRepository, { Q } from './base'
2
- import ContentProgress, { COLLECTION_TYPE, STATE } from '../models/ContentProgress'
2
+ import ContentProgress, { COLLECTION_TYPE, COLLECTION_ID_SELF, STATE } from '../models/ContentProgress'
3
3
 
4
4
  export default class ProgressRepository extends SyncRepository<ContentProgress> {
5
5
  // null collection only
6
6
  async startedIds(limit?: number) {
7
7
  return this.queryAllIds(...[
8
- Q.where('collection_type', null),
9
- Q.where('collection_id', null),
8
+ Q.where('collection_type', COLLECTION_TYPE.SELF),
9
+ Q.where('collection_id', COLLECTION_ID_SELF),
10
10
 
11
11
  Q.where('state', STATE.STARTED),
12
12
  Q.sortBy('updated_at', 'desc'),
@@ -18,8 +18,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
18
18
  // null collection only
19
19
  async completedIds(limit?: number) {
20
20
  return this.queryAllIds(...[
21
- Q.where('collection_type', null),
22
- Q.where('collection_id', null),
21
+ Q.where('collection_type', COLLECTION_TYPE.SELF),
22
+ Q.where('collection_id', COLLECTION_ID_SELF),
23
23
 
24
24
  Q.where('state', STATE.COMPLETED),
25
25
  Q.sortBy('updated_at', 'desc'),
@@ -55,8 +55,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
55
55
  } = {}
56
56
  ) {
57
57
  const clauses: Q.Clause[] = [
58
- Q.where('collection_type', null),
59
- Q.where('collection_id', null),
58
+ Q.where('collection_type', COLLECTION_TYPE.SELF),
59
+ Q.where('collection_id', COLLECTION_ID_SELF),
60
60
 
61
61
  Q.or(Q.where('state', STATE.STARTED), Q.where('state', STATE.COMPLETED)),
62
62
  Q.sortBy('updated_at', 'desc'),
@@ -80,8 +80,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
80
80
  async mostRecentlyUpdatedId(contentIds: number[], collection: { type: COLLECTION_TYPE; id: number } | null = null) {
81
81
  return this.queryOneId(
82
82
  Q.where('content_id', Q.oneOf(contentIds)),
83
- Q.where('collection_type', collection?.type ?? null),
84
- Q.where('collection_id', collection?.id ?? null),
83
+ Q.where('collection_type', collection?.type ?? COLLECTION_TYPE.SELF),
84
+ Q.where('collection_id', collection?.id ?? COLLECTION_ID_SELF),
85
85
 
86
86
  Q.sortBy('updated_at', 'desc')
87
87
  )
@@ -93,8 +93,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
93
93
  ) {
94
94
  const clauses = [
95
95
  Q.where('content_id', contentId),
96
- Q.where('collection_type', collection?.type ?? null),
97
- Q.where('collection_id', collection?.id ?? null),
96
+ Q.where('collection_type', collection?.type ?? COLLECTION_TYPE.SELF),
97
+ Q.where('collection_id', collection?.id ?? COLLECTION_ID_SELF),
98
98
  ]
99
99
 
100
100
  return await this.queryOne(...clauses)
@@ -106,8 +106,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
106
106
  ) {
107
107
  const clauses = [
108
108
  Q.where('content_id', Q.oneOf(contentIds)),
109
- Q.where('collection_type', collection?.type ?? null),
110
- Q.where('collection_id', collection?.id ?? null),
109
+ Q.where('collection_type', collection?.type ?? COLLECTION_TYPE.SELF),
110
+ Q.where('collection_id', collection?.id ?? COLLECTION_ID_SELF),
111
111
  ]
112
112
 
113
113
  return await this.queryAll(...clauses)
@@ -118,8 +118,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
118
118
 
119
119
  const result = this.upsertOne(id, (r) => {
120
120
  r.content_id = contentId
121
- r.collection_type = collection?.type ?? null
122
- r.collection_id = collection?.id ?? null
121
+ r.collection_type = collection?.type ?? COLLECTION_TYPE.SELF
122
+ r.collection_id = collection?.id ?? COLLECTION_ID_SELF
123
123
 
124
124
  r.state = progressPct === 100 ? STATE.COMPLETED : STATE.STARTED
125
125
  r.progress_percent = progressPct
@@ -142,8 +142,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
142
142
  progressPercent: progressPct,
143
143
  progressStatus: progressPct === 100 ? STATE.COMPLETED : STATE.STARTED,
144
144
  bubble: true,
145
- collectionType: collection?.type ?? null,
146
- collectionId: collection?.id ?? null,
145
+ collectionType: collection?.type ?? COLLECTION_TYPE.SELF,
146
+ collectionId: collection?.id ?? COLLECTION_ID_SELF,
147
147
  resumeTimeSeconds: resumeTime ?? null,
148
148
  timestamp: Date.now()
149
149
  })
@@ -165,8 +165,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
165
165
  ProgressRepository.generateId(contentId, collection),
166
166
  (r: ContentProgress) => {
167
167
  r.content_id = contentId
168
- r.collection_type = collection?.type ?? null
169
- r.collection_id = collection?.id ?? null
168
+ r.collection_type = collection?.type ?? COLLECTION_TYPE.SELF
169
+ r.collection_id = collection?.id ?? COLLECTION_ID_SELF
170
170
 
171
171
  r.state = progressPct === 100 ? STATE.COMPLETED : STATE.STARTED
172
172
  r.progress_percent = progressPct
@@ -185,8 +185,8 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
185
185
  ProgressRepository.generateId(+contentId, collection),
186
186
  (r: ContentProgress) => {
187
187
  r.content_id = +contentId
188
- r.collection_type = collection?.type ?? null
189
- r.collection_id = collection?.id ?? null
188
+ r.collection_type = collection?.type ?? COLLECTION_TYPE.SELF
189
+ r.collection_id = collection?.id ?? COLLECTION_ID_SELF
190
190
 
191
191
  r.state = progressPct === 100 ? STATE.COMPLETED : STATE.STARTED
192
192
  r.progress_percent = progressPct
@@ -204,10 +204,6 @@ export default class ProgressRepository extends SyncRepository<ContentProgress>
204
204
  contentId: number,
205
205
  collection: { type: COLLECTION_TYPE; id: number } | null
206
206
  ) {
207
- if (collection) {
208
- return `${contentId}:${collection.type}:${collection.id}`
209
- } else {
210
- return `${contentId}`
211
- }
207
+ return `${contentId}:${collection?.type || COLLECTION_TYPE.SELF}:${collection?.id || COLLECTION_ID_SELF}`
212
208
  }
213
209
  }
@@ -10,7 +10,6 @@ import { fetchLessonsFeaturingThisContent } from '../src/services/sanity.js'
10
10
 
11
11
  const {
12
12
  fetchSongById,
13
- fetchArtists,
14
13
  fetchReturning,
15
14
  fetchLeaving,
16
15
  fetchComingSoon,
@@ -21,25 +20,20 @@ const {
21
20
  fetchByRailContentIds,
22
21
  fetchAll,
23
22
  fetchAllFilterOptions,
24
- fetchFoundation,
25
- fetchMethod,
26
23
  fetchRelatedLessons,
27
24
  fetchAllPacks,
28
25
  fetchPackAll,
29
26
  fetchLessonContent,
30
27
  fetchLiveEvent,
31
- fetchCoachLessons,
32
28
  fetchByReference,
33
29
  fetchScheduledReleases,
34
30
  getSortOrder,
35
31
  fetchShowsData,
36
32
  fetchMetadata,
37
- fetchNextPreviousLesson,
38
33
  fetchHierarchy,
39
34
  fetchTopLevelParentId,
40
35
  fetchOtherSongVersions,
41
36
  fetchCommentModContentData,
42
- fetchMethodPreviousNextLesson,
43
37
  fetchSanity,
44
38
  } = require('../src/services/sanity.js')
45
39
 
@@ -77,13 +71,6 @@ describe('Sanity Queries', function() {
77
71
  expect(response).toBeDefined()
78
72
  })
79
73
 
80
-
81
- test('fetchArtists', async () => {
82
- const response = await fetchArtists('drumeo')
83
- const artistNames = response.map((x) => x.name)
84
- expect(artistNames).toContain('Audioslave')
85
- }, 10000)
86
-
87
74
  test('fetchSongArtistCount', async () => {
88
75
  const response = await fetchSongArtistCount('drumeo')
89
76
  log(response)
@@ -301,13 +288,6 @@ describe('Sanity Queries', function() {
301
288
  expect(sort).toBe('published_on asc')
302
289
  })
303
290
 
304
- test('fetchMethod', async () => {
305
- const response = await fetchMethod('drumeo', 'drumeo-method')
306
- log(response)
307
- expect(response).toBeDefined()
308
- expect(response.levels.length).toBeGreaterThan(0)
309
- })
310
-
311
291
  test('fetchAll-WithProgress', async () => {
312
292
  const ids = [410213, 410215]
313
293
  let response = await fetchAll('drumeo', 'song', {
@@ -332,13 +312,6 @@ describe('Sanity Queries', function() {
332
312
  expect(response.meta.totalResults).toBe(0)
333
313
  })
334
314
 
335
- test('fetchFoundation', async () => {
336
- const response = await fetchFoundation('foundations-2019')
337
- log(response)
338
- expect(response.units.length).toBeGreaterThan(0)
339
- expect(response.type).toBe('foundation')
340
- })
341
-
342
315
  test('fetchPackAll', async () => {
343
316
  const response = await fetchPackAll(212899) //https://web-staging-one.musora.com/admin/studio/publishing/structure/pack;pack_212899%2Cinspect%3Don
344
317
  log(response)
@@ -357,35 +330,6 @@ describe('Sanity Queries', function() {
357
330
  expect(response[0].id).toBe(212899)
358
331
  })
359
332
 
360
- test('fetchCoachLessons', async () => {
361
- const response = await fetchCoachLessons('drumeo', 411493, {})
362
- expect(response.entity.length).toBeGreaterThan(0)
363
- })
364
- test('fetchCoachLessons-WithTypeFilters', async () => {
365
- const response = await fetchAllFilterOptions('drumeo', ['type,course', 'type,live'], '', '', 'coach-lessons', '', [], 31880)
366
- log(response)
367
- expect(response.meta.filterOptions.difficulty).toBeDefined()
368
- expect(response.meta.filterOptions.type).toBeDefined()
369
- expect(response.meta.filterOptions.lifestyle).toBeDefined()
370
- expect(response.meta.filterOptions.genre).toBeDefined()
371
- })
372
-
373
- test('fetchCoachLessons-WithTypeFilters-InvalidContentType', async () => {
374
- const brand = 'drumeo'
375
- const coachId = 31880
376
- const invalidContentType = 'course' // Not 'coach-lessons'
377
-
378
- await expect(fetchAllFilterOptions(brand, ['type,course', 'type,live'], '', '', invalidContentType, '', [], coachId)).rejects.toThrow(`Invalid contentType: 'course' for coachId. It must be 'coach-lessons'.`)
379
- })
380
-
381
- test('fetchCoachLessons-IncludedFields', async () => {
382
- const response = await fetchCoachLessons('drumeo', 31880, {
383
- includedFields: ['genre,Pop/Rock', 'difficulty,Beginner'],
384
- })
385
- log(response)
386
- expect(response.entity.length).toBeGreaterThan(0)
387
- })
388
-
389
333
  test('fetchAll-IncludedFields', async () => {
390
334
  let response = await fetchAll('drumeo', 'instructor', { includedFields: ['is_active'] })
391
335
  console.log(response)
@@ -488,66 +432,6 @@ describe('Sanity Queries', function() {
488
432
  expect(response).toBeDefined()
489
433
  })
490
434
 
491
- test('fetchNextPreviousLesson-Show-With-Episodes', async () => {
492
- const id = 227136
493
- const document = await fetchByRailContentId(id, 'behind-the-scenes')
494
- const response = await fetchNextPreviousLesson(id)
495
- log(response)
496
- expect(response.prevLesson).toBeDefined()
497
- expect(response.prevLesson.sort).toBeLessThanOrEqual(document.sort)
498
- expect(response.nextLesson).toBeDefined()
499
- expect(response.nextLesson.sort).toBeGreaterThanOrEqual(document.sort)
500
- })
501
-
502
- test('fetchMethodNextPreviousLesson-Last', async () => {
503
- const id = 260171
504
- const methodId = 259060
505
- const response = await fetchMethodPreviousNextLesson(id, methodId)
506
- log(response)
507
- expect(response.prevLesson).toBeDefined()
508
- expect(response.prevLesson.id).toBe(260170)
509
- expect(response.prevLesson.type).toBe('course-part')
510
- expect(response.nextLesson).not.toBeDefined()
511
- })
512
-
513
- test('fetchNextPreviousLesson-Method-Lesson', async () => {
514
- const id = 241265
515
- const response = await fetchNextPreviousLesson(id)
516
- log(response)
517
- expect(response.prevLesson).toBeDefined()
518
- expect(response.prevLesson.id).toBe(241264)
519
- expect(response.prevLesson.type).toBe('learning-path-lesson')
520
- expect(response.nextLesson).toBeDefined()
521
- expect(response.nextLesson.id).toBe(241267)
522
- expect(response.nextLesson.type).toBe('learning-path-lesson')
523
- })
524
-
525
- test('fetchNextPreviousLesson-Quick-Tips', async () => {
526
- const id = 412277
527
- const response = await fetchNextPreviousLesson(id)
528
- const document = await fetchByRailContentId(id, 'quick-tips')
529
- const documentPublishedOn = new Date(document.published_on)
530
- const prevDocumentPublishedOn = new Date(response.prevLesson.published_on)
531
- const nextDocumentPublishedOn = new Date(response.nextLesson.published_on)
532
- expect(response.prevLesson).toBeDefined()
533
- expect(prevDocumentPublishedOn.getTime()).toBeLessThan(documentPublishedOn.getTime())
534
- expect(response.nextLesson).toBeDefined()
535
- expect(documentPublishedOn.getTime()).toBeLessThan(nextDocumentPublishedOn.getTime())
536
- })
537
-
538
- test('fetchNextPreviousLesson-Song', async () => {
539
- const id = 414041
540
- const response = await fetchNextPreviousLesson(id)
541
- const document = await fetchByRailContentId(id, 'song')
542
- const documentPublishedOn = new Date(document.published_on)
543
- const prevDocumentPublishedOn = new Date(response.prevLesson.published_on)
544
- const nextDocumentPublishedOn = new Date(response.nextLesson.published_on)
545
- expect(response.prevLesson).toBeDefined()
546
- expect(prevDocumentPublishedOn.getTime()).toBeLessThanOrEqual(documentPublishedOn.getTime())
547
- expect(response.nextLesson).toBeDefined()
548
- expect(documentPublishedOn.getTime()).toBeLessThanOrEqual(nextDocumentPublishedOn.getTime())
549
- })
550
-
551
435
  test('fetchTopLevelParentId', async () => {
552
436
  let contentId = await fetchTopLevelParentId(241250)
553
437
  expect(contentId).toBe(241247)