musora-content-services 2.140.9 → 2.142.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 CHANGED
@@ -2,6 +2,34 @@
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.142.0](https://github.com/railroadmedia/musora-content-services/compare/v2.141.2...v2.142.0) (2026-03-25)
6
+
7
+
8
+ ### Features
9
+
10
+ * **MU2-1387:** store paywall skipping on onboarding data ([#875](https://github.com/railroadmedia/musora-content-services/issues/875)) ([11d0459](https://github.com/railroadmedia/musora-content-services/commit/11d0459fef4cb72f29951137901dcb8ec7bdf8f4))
11
+
12
+ ### [2.141.2](https://github.com/railroadmedia/musora-content-services/compare/v2.141.1...v2.141.2) (2026-03-25)
13
+
14
+ ### [2.141.1](https://github.com/railroadmedia/musora-content-services/compare/v2.141.0...v2.141.1) (2026-03-25)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **TP-1166:** set watermelon DB namespacing based on environment ([#884](https://github.com/railroadmedia/musora-content-services/issues/884)) ([fe16b68](https://github.com/railroadmedia/musora-content-services/commit/fe16b68fbde371fdffb4f2673218e1d2a4ab016d))
20
+
21
+ ## [2.141.0](https://github.com/railroadmedia/musora-content-services/compare/v2.140.9...v2.141.0) (2026-03-25)
22
+
23
+
24
+ ### Features
25
+
26
+ * change your progress section to display parents ([#883](https://github.com/railroadmedia/musora-content-services/issues/883)) ([66e4678](https://github.com/railroadmedia/musora-content-services/commit/66e4678f20c781c5d66c59e5c9ce488c63dc5301))
27
+
28
+
29
+ ### Bug Fixes
30
+
31
+ * **T3PS-2319:** setup livestream progress ([#878](https://github.com/railroadmedia/musora-content-services/issues/878)) ([d1284c6](https://github.com/railroadmedia/musora-content-services/commit/d1284c69bf35cd4cdaf9a4b448767dc615a6dbf1))
32
+
5
33
  ### [2.140.9](https://github.com/railroadmedia/musora-content-services/compare/v2.140.8...v2.140.9) (2026-03-24)
6
34
 
7
35
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.140.9",
3
+ "version": "2.142.0",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -367,6 +367,7 @@ export const parentRecentTypes = [
367
367
  'play-along',
368
368
  'jam-track',
369
369
  'song-tutorial',
370
+ ...liveArchivesLessonTypes,
370
371
  ]
371
372
 
372
373
  const songsRecentTypes = [...SONG_TYPES]
@@ -374,7 +375,7 @@ const songsRecentTypes = [...SONG_TYPES]
374
375
  export const recentTypes = {
375
376
  lessons: lessonRecentTypes,
376
377
  songs: songsRecentTypes,
377
- home: [...lessonRecentTypes, ...songsRecentTypes],
378
+ home: parentRecentTypes,
378
379
  homeRow: parentRecentTypes,
379
380
  }
380
381
 
@@ -672,7 +673,7 @@ export let contentTypeConfig = {
672
673
  ],
673
674
  'new-and-scheduled': {
674
675
  fields: [
675
- 'show_in_new_feed',
676
+ 'show_in_new_feed',
676
677
  isLiveField()
677
678
  ],
678
679
  },
package/src/index.d.ts CHANGED
@@ -17,6 +17,7 @@ import {
17
17
 
18
18
  import {
19
19
  globalConfig,
20
+ initializeEnvVar,
20
21
  initializeService
21
22
  } from './services/config.js';
22
23
 
@@ -113,6 +114,7 @@ import {
113
114
  contentStatusCompletedMany,
114
115
  contentStatusReset,
115
116
  contentStatusStarted,
117
+ extractFromRecordId,
116
118
  flushWatchSession,
117
119
  generateRecordId,
118
120
  getAllCompleted,
@@ -499,6 +501,7 @@ declare module 'musora-content-services' {
499
501
  editComment,
500
502
  emitProgressSaved,
501
503
  enrollUserInGuidedCourse,
504
+ extractFromRecordId,
502
505
  extractSanityUrl,
503
506
  fetchAll,
504
507
  fetchAllFilterOptions,
@@ -665,6 +668,7 @@ declare module 'musora-content-services' {
665
668
  getWeekNumber,
666
669
  globalConfig,
667
670
  guidedCourses,
671
+ initializeEnvVar,
668
672
  initializeService,
669
673
  isBucketUrl,
670
674
  isContentLiked,
package/src/index.js CHANGED
@@ -21,6 +21,7 @@ import {
21
21
 
22
22
  import {
23
23
  globalConfig,
24
+ initializeEnvVar,
24
25
  initializeService
25
26
  } from './services/config.js';
26
27
 
@@ -117,6 +118,7 @@ import {
117
118
  contentStatusCompletedMany,
118
119
  contentStatusReset,
119
120
  contentStatusStarted,
121
+ extractFromRecordId,
120
122
  flushWatchSession,
121
123
  generateRecordId,
122
124
  getAllCompleted,
@@ -498,6 +500,7 @@ export {
498
500
  editComment,
499
501
  emitProgressSaved,
500
502
  enrollUserInGuidedCourse,
503
+ extractFromRecordId,
501
504
  extractSanityUrl,
502
505
  fetchAll,
503
506
  fetchAllFilterOptions,
@@ -664,6 +667,7 @@ export {
664
667
  getWeekNumber,
665
668
  globalConfig,
666
669
  guidedCourses,
670
+ initializeEnvVar,
667
671
  initializeService,
668
672
  isBucketUrl,
669
673
  isContentLiked,
@@ -54,6 +54,7 @@ const excludeFromGeneratedIndex = []
54
54
  * localStorage: localStorage,
55
55
  * isMA: false,
56
56
  * permissionsVersion: 'v1', // Optional: 'v1' (default) or 'v2'
57
+ * appEnv: 'local'
57
58
  * });
58
59
  *
59
60
  * @example React Native Application
@@ -66,6 +67,9 @@ const excludeFromGeneratedIndex = []
66
67
  * baseUrl: 'https://web-staging-one.musora.com',
67
68
  * localStorage: AsyncStorage,
68
69
  * isMA: true,
70
+ * localTimezoneString: '',
71
+ * permissionsVersion: 'v2',
72
+ * appEnv: 'local'
69
73
  * });
70
74
  */
71
75
  export function initializeService(config) {
@@ -86,3 +90,7 @@ export function initializeService(config) {
86
90
  })
87
91
  }
88
92
  }
93
+
94
+ export function initializeEnvVar(config) {
95
+ globalConfig.appEnv = config.appEnv
96
+ }
@@ -399,12 +399,16 @@ async function _getAllStartedOrCompleted({
399
399
  * Record watch session
400
400
  * @return {string} sessionId - provide in future calls to update progress
401
401
  * @param {int} contentId
402
- * @param {int} mediaLengthSeconds
403
- * @param {int} currentSeconds
404
- * @param {int} secondsPlayed
405
- * @param {string} sessionId - This function records a sessionId to pass into future updates to progress on the same video
406
- * @param {int} instrumentId - enum value of instrument id
407
- * @param {int} categoryId - enum value of category id
402
+ * @param {any} collection - progress collection context, null if a-la-carte
403
+ * @param {string} collection.type - enum value of collection type
404
+ * @param {int} collection.id - content_id of parent collection (e.g. learning path content_id)
405
+ * @param {int} mediaLengthSeconds - total length of video media || live event duration if livestream
406
+ * @param {int} currentSeconds - seconds timestamp relative to beginning of video
407
+ * @param {int} secondsPlayed - seconds played in this watch session (since last pause)
408
+ * @param {any} prevSession - This function records a sessionId to pass into future updates to progress on the same video
409
+ * @param {int|null} instrumentId - enum value of instrument id
410
+ * @param {int|null} categoryId - enum value of category id
411
+ * @param {boolean} isLivestream - determines livestream-specific progress handling
408
412
  */
409
413
  export async function recordWatchSession(
410
414
  contentId,
@@ -414,7 +418,8 @@ export async function recordWatchSession(
414
418
  secondsPlayed,
415
419
  prevSession = null,
416
420
  instrumentId = null,
417
- categoryId = null
421
+ categoryId = null,
422
+ isLivestream = false,
418
423
  ) {
419
424
  contentId = normalizeContentId(contentId)
420
425
  collection = normalizeCollection(collection)
@@ -428,7 +433,7 @@ export async function recordWatchSession(
428
433
  // Track practice and progress locally (no immediate push)
429
434
  await Promise.all([
430
435
  trackPractice(contentId, secondsPlayed, { instrumentId, categoryId }),
431
- trackProgress(contentId, collection, currentSeconds, mediaLengthSeconds),
436
+ trackProgress(contentId, collection, currentSeconds, mediaLengthSeconds, isLivestream),
432
437
  ])
433
438
 
434
439
  if (!prevSession.pushInterval) {
@@ -453,11 +458,17 @@ async function trackPractice(contentId, secondsPlayed, details = {}) {
453
458
  return trackUserPractice(contentId, secondsPlayed, details)
454
459
  }
455
460
 
456
- async function trackProgress(contentId, collection, currentSeconds, mediaLengthSeconds) {
461
+ async function trackProgress(contentId, collection, currentSeconds, mediaLengthSeconds, isLivestream = false) {
457
462
  const progress = Math.max(1, Math.min(
458
463
  99,
459
464
  Math.round(((currentSeconds ?? 0) / Math.max(1, mediaLengthSeconds)) * 100)
460
465
  ))
466
+
467
+ if (isLivestream) {
468
+ // resumeTime of a livestream will far exceed VOD length, so set to 0
469
+ // doesn't affect livestream resumeTime, but will send users to 0 seconds in VOD
470
+ currentSeconds = 0
471
+ }
461
472
  return saveContentProgress(contentId, collection, progress, currentSeconds, { skipPush: true })
462
473
  }
463
474
 
@@ -1,6 +1,7 @@
1
1
  import schema from '../schema'
2
2
  import type { SyncUserScope } from '../index'
3
3
  import { SyncError } from '../errors'
4
+ import { globalConfig } from '../../config.js'
4
5
 
5
6
  import type { default as SQLiteAdapter, SQLiteExtensions } from './sqlite'
6
7
  import type LokiJSAdapter from './lokijs'
@@ -32,9 +33,11 @@ export default function syncAdapterFactory<T extends DatabaseAdapter>(
32
33
  throw new SyncError('User ID is required to construct database adapter')
33
34
  }
34
35
 
36
+ const envName = globalConfig.appEnv || 'production'
37
+ const dbSuffix = envName === 'production' ? '' : (':' + (envName))
35
38
  const adapter = new AdapterClass({
36
39
  ...opts,
37
- dbName: `musora:sync:${userScope.initialId}`,
40
+ dbName: `musora:sync:${userScope.initialId}${dbSuffix}`,
38
41
  schema,
39
42
  migrations: undefined
40
43
  }, extensions)
@@ -40,4 +40,5 @@
40
40
  * @property {boolean} isMA - Variable that tells if the library is used by MA or FEW
41
41
  * @property {string} localTimezoneString - The local timezone string in format: America/Vancouver
42
42
  * @property {('v1'|'v2')} [permissionsVersion='v1'] - Permissions system version to use ('v1' or 'v2')
43
+ * @property {string} appEnv - App environment name
43
44
  */
@@ -39,6 +39,7 @@ export interface Onboarding {
39
39
  is_completed: boolean
40
40
  completed_at: Date | null
41
41
  marketing_opt_in: boolean
42
+ has_skipped_paywall: boolean
42
43
  }
43
44
 
44
45
  /**
@@ -59,8 +60,8 @@ export async function startOnboarding({
59
60
  brand,
60
61
  flow,
61
62
  steps,
62
- marketing_opt_in: marketingOptIn,
63
63
  is_completed: false,
64
+ marketing_opt_in: marketingOptIn,
64
65
  })
65
66
  }
66
67
 
@@ -69,8 +70,9 @@ export interface UpdateOnboardingParams {
69
70
  email: string
70
71
  brand: string
71
72
  flow: string
72
- marketingOptIn: boolean
73
73
  is_completed?: boolean
74
+ marketingOptIn?: boolean
75
+ hasSkippedPaywall?: boolean
74
76
  steps: OnboardingSteps
75
77
  }
76
78
 
@@ -88,6 +90,7 @@ export async function updateOnboarding({
88
90
  steps,
89
91
  is_completed = false,
90
92
  marketingOptIn = false,
93
+ hasSkippedPaywall = false,
91
94
  }: UpdateOnboardingParams): Promise<Onboarding> {
92
95
  return PUT(`/api/user-management-system/v1/onboardings/${id}`, {
93
96
  email,
@@ -96,6 +99,7 @@ export async function updateOnboarding({
96
99
  steps,
97
100
  is_completed,
98
101
  marketing_opt_in: marketingOptIn,
102
+ has_skipped_paywall: hasSkippedPaywall,
99
103
  })
100
104
  }
101
105
 
@@ -1,9 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(rg:*)",
5
- "Bash(npm run lint:*)"
6
- ],
7
- "deny": []
8
- }
9
- }