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 +28 -0
- package/package.json +1 -1
- package/src/contentTypeConfig.js +3 -2
- package/src/index.d.ts +4 -0
- package/src/index.js +4 -0
- package/src/services/config.js +8 -0
- package/src/services/contentProgress.js +20 -9
- package/src/services/sync/adapters/factory.ts +4 -1
- package/src/services/types.js +1 -0
- package/src/services/user/onboarding.ts +6 -2
- package/.claude/settings.local.json +0 -9
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
package/src/contentTypeConfig.js
CHANGED
|
@@ -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:
|
|
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,
|
package/src/services/config.js
CHANGED
|
@@ -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 {
|
|
403
|
-
* @param {
|
|
404
|
-
* @param {int}
|
|
405
|
-
* @param {
|
|
406
|
-
* @param {int}
|
|
407
|
-
* @param {int}
|
|
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)
|
package/src/services/types.js
CHANGED
|
@@ -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
|
|