musora-content-services 2.36.2 → 2.36.4

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,10 @@
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.36.4](https://github.com/railroadmedia/musora-content-services/compare/v2.36.3...v2.36.4) (2025-09-10)
6
+
7
+ ### [2.36.3](https://github.com/railroadmedia/musora-content-services/compare/v2.36.2...v2.36.3) (2025-09-09)
8
+
5
9
  ### [2.36.2](https://github.com/railroadmedia/musora-content-services/compare/v2.36.1...v2.36.2) (2025-09-09)
6
10
 
7
11
  ### [2.36.1](https://github.com/railroadmedia/musora-content-services/compare/v2.36.0...v2.36.1) (2025-09-09)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.36.2",
3
+ "version": "2.36.4",
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
@@ -10,7 +10,6 @@ import {
10
10
  fetchEnrollmentPageMetadata,
11
11
  guidedCourses,
12
12
  pinGuidedCourse,
13
- pinnedGuidedCourses,
14
13
  unEnrollUserInGuidedCourse,
15
14
  unPinGuidedCourse
16
15
  } from './services/content-org/guided-courses.ts';
@@ -59,6 +58,7 @@ import {
59
58
  import {
60
59
  contentStatusCompleted,
61
60
  contentStatusReset,
61
+ contentStatusStartedForGuidedCourseEnrollment,
62
62
  getAllCompleted,
63
63
  getAllStarted,
64
64
  getAllStartedOrCompleted,
@@ -149,6 +149,7 @@ import {
149
149
  postContentLiked,
150
150
  postContentReset,
151
151
  postContentRestore,
152
+ postContentStartForGC,
152
153
  postContentUnliked,
153
154
  postPlaylistContentEngaged,
154
155
  postRecordWatchSession,
@@ -338,6 +339,7 @@ declare module 'musora-content-services' {
338
339
  confirmEmailChange,
339
340
  contentStatusCompleted,
340
341
  contentStatusReset,
342
+ contentStatusStartedForGuidedCourseEnrollment,
341
343
  convertToTimeZone,
342
344
  createComment,
343
345
  createPlaylist,
@@ -508,11 +510,11 @@ declare module 'musora-content-services' {
508
510
  pauseLiveEventPolling,
509
511
  pinGuidedCourse,
510
512
  pinProgressRow,
511
- pinnedGuidedCourses,
512
513
  postContentComplete,
513
514
  postContentLiked,
514
515
  postContentReset,
515
516
  postContentRestore,
517
+ postContentStartForGC,
516
518
  postContentUnliked,
517
519
  postPlaylistContentEngaged,
518
520
  postRecordWatchSession,
package/src/index.js CHANGED
@@ -10,7 +10,6 @@ import {
10
10
  fetchEnrollmentPageMetadata,
11
11
  guidedCourses,
12
12
  pinGuidedCourse,
13
- pinnedGuidedCourses,
14
13
  unEnrollUserInGuidedCourse,
15
14
  unPinGuidedCourse
16
15
  } from './services/content-org/guided-courses.ts';
@@ -59,6 +58,7 @@ import {
59
58
  import {
60
59
  contentStatusCompleted,
61
60
  contentStatusReset,
61
+ contentStatusStartedForGuidedCourseEnrollment,
62
62
  getAllCompleted,
63
63
  getAllStarted,
64
64
  getAllStartedOrCompleted,
@@ -149,6 +149,7 @@ import {
149
149
  postContentLiked,
150
150
  postContentReset,
151
151
  postContentRestore,
152
+ postContentStartForGC,
152
153
  postContentUnliked,
153
154
  postPlaylistContentEngaged,
154
155
  postRecordWatchSession,
@@ -337,6 +338,7 @@ export {
337
338
  confirmEmailChange,
338
339
  contentStatusCompleted,
339
340
  contentStatusReset,
341
+ contentStatusStartedForGuidedCourseEnrollment,
340
342
  convertToTimeZone,
341
343
  createComment,
342
344
  createPlaylist,
@@ -507,11 +509,11 @@ export {
507
509
  pauseLiveEventPolling,
508
510
  pinGuidedCourse,
509
511
  pinProgressRow,
510
- pinnedGuidedCourses,
511
512
  postContentComplete,
512
513
  postContentLiked,
513
514
  postContentReset,
514
515
  postContentRestore,
516
+ postContentStartForGC,
515
517
  postContentUnliked,
516
518
  postPlaylistContentEngaged,
517
519
  postRecordWatchSession,
@@ -12,6 +12,7 @@ export async function fetchJSONHandler(
12
12
  'Content-Type': 'application/json',
13
13
  Accept: 'application/json',
14
14
  'X-CSRF-TOKEN': token,
15
+ credentials: 'include',
15
16
  }
16
17
 
17
18
  if (body) {
@@ -39,8 +39,3 @@ export async function guidedCourses() {
39
39
  const url: string = `${BASE_PATH}/v1/user/guided-courses/`
40
40
  return await fetchHandler(url, 'GET')
41
41
  }
42
-
43
- export async function pinnedGuidedCourses(brand) {
44
- const url: string = `${BASE_PATH}/v1/user/guided-courses/pinned?brand=${brand}`
45
- return await fetchHandler(url, 'GET')
46
- }
@@ -93,7 +93,6 @@ export async function addContextToContent(dataPromise, ...dataArgs)
93
93
  addNextLesson ? getNextLesson(items) : Promise.resolve(null),
94
94
  addNavigateTo ? getNavigateTo(items) : Promise.resolve(null),
95
95
  ])
96
- if (addNextLesson) console.log('AddNextLesson is depreciated in favour of addNavigateTo')
97
96
 
98
97
  const addContext = async (item) => ({
99
98
  ...item,
@@ -2,6 +2,7 @@ import {
2
2
  fetchContentProgress,
3
3
  postContentComplete,
4
4
  postContentReset,
5
+ postContentStartForGC,
5
6
  postRecordWatchSession,
6
7
  } from './railcontent.js'
7
8
  import { DataContext, ContentProgressVersionKey } from './dataContext.js'
@@ -359,6 +360,19 @@ export async function contentStatusCompleted(contentId) {
359
360
  }
360
361
  )
361
362
  }
363
+ export async function contentStatusStartedForGuidedCourseEnrollment(contentId) {
364
+ const response = await postContentStartForGC(contentId);
365
+
366
+ return await dataContext.update(
367
+ async function (localContext) {
368
+ let hierarchy = await fetchHierarchy(contentId)
369
+ startStatusInLocalContext(localContext, contentId, hierarchy)
370
+ },
371
+ async function () {
372
+ return response
373
+ }
374
+ )
375
+ }
362
376
 
363
377
  function saveContentProgress(localContext, contentId, progress, currentSeconds, hierarchy) {
364
378
  if (progress === 100) {
@@ -395,6 +409,22 @@ function completeStatusInLocalContext(localContext, contentId, hierarchy) {
395
409
  bubbleProgress(hierarchy, contentId, localContext)
396
410
  }
397
411
 
412
+ function startStatusInLocalContext(localContext, contentId, hierarchy) {
413
+ let data = localContext.data[contentId] ?? {}
414
+ data[DATA_KEY_PROGRESS] = 0
415
+ data[DATA_KEY_STATUS] = STATE_STARTED
416
+ data[DATA_KEY_LAST_UPDATED_TIME] = Math.round(new Date().getTime() / 1000)
417
+ localContext.data[contentId] = data
418
+
419
+ if (!hierarchy) return
420
+ let children = hierarchy.children[contentId] ?? []
421
+ for (let i = 0; i < children.length; i++) {
422
+ let childId = children[i]
423
+ startStatusInLocalContext(localContext, childId, hierarchy)
424
+ }
425
+ bubbleProgress(hierarchy, contentId, localContext)
426
+ }
427
+
398
428
  function getChildrenToDepth(parentId, hierarchy, depth = 1) {
399
429
  let childIds = hierarchy.children[parentId] ?? []
400
430
  let allChildrenIds = childIds
@@ -388,6 +388,16 @@ export async function postContentComplete(contentId) {
388
388
  return postDataHandler(url)
389
389
  }
390
390
 
391
+ /**
392
+ * start a Guided Course content's progress for a given user
393
+ * @param contentId
394
+ * @returns {Promise<any|string|null>}
395
+ */
396
+ export async function postContentStartForGC(contentId) {
397
+ let url = `/api/content/v1/user/progress/start`
398
+ return postDataHandler(url, { contentId })
399
+ }
400
+
391
401
  /**
392
402
  * resets the user's progress on a content
393
403
  * @param contentId
@@ -1834,9 +1834,6 @@ export async function fetchSanity(
1834
1834
  }
1835
1835
  const result = await response.json()
1836
1836
  if (result.result) {
1837
- if (globalConfig.sanityConfig.debug) {
1838
- console.log('fetchSanity Results:', result)
1839
- }
1840
1837
  let results = isList ? result.result : result.result[0]
1841
1838
  if (!results) {
1842
1839
  throw new Error('No results found')
@@ -45,6 +45,21 @@ export async function login(email, password, deviceName, deviceToken, platform)
45
45
  })
46
46
  }
47
47
 
48
+ export async function loginWithProvider(provider, token) {
49
+ const baseUrl = `${globalConfig.baseUrl}/api/user-management-system`
50
+ return fetch(`${baseUrl}/v1/sessions`, {
51
+ method: 'POST',
52
+ headers: {
53
+ 'Content-Type': 'application/json',
54
+ 'X-Client-Platform': 'mobile',
55
+ Authorization: null,
56
+ },
57
+ body: JSON.stringify({
58
+ provider: provider,
59
+ token: token,
60
+ }),
61
+ });
62
+ }
48
63
  /**
49
64
  * Logs the user out of the current session.
50
65
  *
@@ -13,7 +13,7 @@ import {
13
13
  import { DataContext, UserActivityVersionKey } from './dataContext.js'
14
14
  import { fetchByRailContentId, fetchByRailContentIds, fetchShows } from './sanity'
15
15
  import { fetchPlaylist, fetchUserPlaylists } from './content-org/playlists'
16
- import {guidedCourses, pinnedGuidedCourses} from './content-org/guided-courses'
16
+ import {guidedCourses} from './content-org/guided-courses'
17
17
  import {
18
18
  getMonday,
19
19
  getWeekNumber,
@@ -950,7 +950,6 @@ async function extractPinnedItemsAndSortAllItems(
950
950
  userPinnedItem,
951
951
  contentsMap,
952
952
  eligiblePlaylistItems,
953
- pinnedGuidedCourse,
954
953
  limit
955
954
  ) {
956
955
  let pinnedItem = await popPinnedItemFromContentsOrPlaylistMap(
@@ -959,22 +958,8 @@ async function extractPinnedItemsAndSortAllItems(
959
958
  eligiblePlaylistItems
960
959
  )
961
960
 
962
- const guidedCourseID = pinnedGuidedCourse?.content_id
963
961
  let combined = []
964
- if (pinnedGuidedCourse) {
965
- const guidedCourseContent =
966
- contentsMap.get(guidedCourseID) ??
967
- (await addContextToContent(fetchByRailContentId, guidedCourseID, 'guided-course', {
968
- addNextLesson: true,
969
- addNavigateTo: true,
970
- addProgressStatus: true,
971
- addProgressPercentage: true,
972
- addProgressTimestamp: true,
973
- }))
974
- contentsMap = popContentAndRemoveChildrenFromContentsMap(guidedCourseContent, contentsMap)
975
- guidedCourseContent.pinned = true
976
- combined.push(guidedCourseContent)
977
- }
962
+
978
963
  if (pinnedItem) {
979
964
  pinnedItem.pinned = true
980
965
  combined.push(pinnedItem)
@@ -1052,20 +1037,15 @@ function generateContentsMap(contents, playlistsContents) {
1052
1037
  export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1053
1038
  // TODO slice progress to a reasonable number, say 100
1054
1039
 
1055
- const [recentPlaylists, progressContents, allPinnedGuidedCourse, userPinnedItem, enrolledGuidedCourses] =
1040
+ const [recentPlaylists, progressContents, userPinnedItem, enrolledGuidedCourses] =
1056
1041
  await Promise.all([
1057
1042
  fetchUserPlaylists(brand, { sort: '-last_progress', limit: limit }),
1058
1043
  getAllStartedOrCompleted({ onlyIds: false, brand: brand }),
1059
- pinnedGuidedCourses(brand),
1060
1044
  getUserPinnedItem(brand),
1061
1045
  guidedCourses()
1062
1046
  ])
1063
1047
 
1064
1048
  const enrolledGuidedCoursesIds = enrolledGuidedCourses.map(course => String(course.content_id));
1065
-
1066
- const mergedGuidedCourses = 1 //get all cuigded courses, incl no progress.
1067
- let pinnedGuidedCourse = allPinnedGuidedCourse?.[0] ?? null
1068
-
1069
1049
  const playlists = recentPlaylists?.data || []
1070
1050
  const eligiblePlaylistItems = await getEligiblePlaylistItems(playlists)
1071
1051
  const playlistEngagedOnContents = eligiblePlaylistItems.map(
@@ -1079,8 +1059,6 @@ export async function getProgressRows({ brand = null, limit = 8 } = {}) {
1079
1059
  if (userPinnedItem?.progressType === 'content') {
1080
1060
  nonPlaylistContentIds.push(userPinnedItem.id)
1081
1061
  }
1082
- console.log("nonPlaylistContentIds",nonPlaylistContentIds)
1083
-
1084
1062
 
1085
1063
  const [playlistsContents, contents] = await Promise.all([
1086
1064
  playlistEngagedOnContents ? addContextToContent(fetchByRailContentIds, playlistEngagedOnContents, 'progress-tracker', {
@@ -1103,7 +1081,6 @@ console.log("nonPlaylistContentIds",nonPlaylistContentIds)
1103
1081
  userPinnedItem,
1104
1082
  contentsMap,
1105
1083
  eligiblePlaylistItems,
1106
- pinnedGuidedCourse,
1107
1084
  limit
1108
1085
  )
1109
1086
  const results = await Promise.all(
@@ -1361,8 +1338,10 @@ export function findIncompleteLesson(progressOnItems, currentContentId, contentT
1361
1338
 
1362
1339
  async function popPinnedItemFromContentsOrPlaylistMap(pinned, contentsMap, playlistItems) {
1363
1340
  if (!pinned) return null
1364
- const { id, progressType, pinnedAt } = pinned
1341
+ const { id, pinnedAt } = pinned
1365
1342
  let item = null
1343
+ const progressType = pinned.progressType ?? pinned.type;
1344
+
1366
1345
  if (progressType === 'content') {
1367
1346
  const pinnedId = parseInt(id)
1368
1347
  if (contentsMap.has(pinnedId)) {
@@ -1399,15 +1378,19 @@ async function popPinnedItemFromContentsOrPlaylistMap(pinned, contentsMap, playl
1399
1378
  }
1400
1379
 
1401
1380
  function popContentAndRemoveChildrenFromContentsMap(content, contentsMap) {
1402
- const children = content.children.map((child) => child.id)
1403
- if (contentsMap.has(content.id)) {
1404
- contentsMap.delete(content.id)
1405
- }
1406
- children.forEach((child) => {
1407
- if (contentsMap.has(child)) {
1408
- contentsMap.delete(child)
1381
+ if (!content.children || content.children.length === 0){
1382
+ console.warn(`content ${content.id} has no children`, content);
1383
+ } else {
1384
+ const children = content.children.map((child) => child.id)
1385
+ if (contentsMap.has(content.id)) {
1386
+ contentsMap.delete(content.id)
1409
1387
  }
1410
- })
1388
+ children.forEach((child) => {
1389
+ if (contentsMap.has(child)) {
1390
+ contentsMap.delete(child)
1391
+ }
1392
+ })
1393
+ }
1411
1394
  return contentsMap
1412
1395
  }
1413
1396
 
@@ -1427,7 +1410,7 @@ function popContentAndRemoveChildrenFromContentsMap(content, contentsMap) {
1427
1410
  export async function pinProgressRow(brand, id, progressType) {
1428
1411
  const url = `/api/user-management-system/v1/progress/pin?brand=${brand}&id=${id}&progressType=${progressType}`
1429
1412
  const response = await fetchHandler(url, 'PUT', null)
1430
- if (response && !response.error && response['action'] === 'update_user_pin') {
1413
+ if (response && !response.error) {
1431
1414
  await updateUserPinnedProgressRow(brand, {
1432
1415
  id,
1433
1416
  progressType,