musora-content-services 2.97.0 → 2.99.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,37 @@
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.99.0](https://github.com/railroadmedia/musora-content-services/compare/v2.98.0...v2.99.0) (2025-12-09)
6
+
7
+
8
+ ### Features
9
+
10
+ * **BEH-1421:** Content Migration : child lesson type migrations ([#624](https://github.com/railroadmedia/musora-content-services/issues/624)) ([77300ed](https://github.com/railroadmedia/musora-content-services/commit/77300eddabc4deed46c26f7b1291d9540a3ef486))
11
+
12
+ ## [2.98.0](https://github.com/railroadmedia/musora-content-services/compare/v2.94.7...v2.98.0) (2025-12-09)
13
+
14
+
15
+ ### Features
16
+
17
+ * **BEH-1195:** Awards System ([#606](https://github.com/railroadmedia/musora-content-services/issues/606)) ([a6ffd92](https://github.com/railroadmedia/musora-content-services/commit/a6ffd92ae518c8e530d4ef743f2649725fddb285))
18
+ * **BEH-1458:** method addcontexttocontent ([#633](https://github.com/railroadmedia/musora-content-services/issues/633)) ([95a2b0a](https://github.com/railroadmedia/musora-content-services/commit/95a2b0ae3f011e17f92b78ad4fcd1ebe7a2342ca))
19
+ * handle learning path complete logic ([#628](https://github.com/railroadmedia/musora-content-services/issues/628)) ([e5266d2](https://github.com/railroadmedia/musora-content-services/commit/e5266d2219597fc295dab97cec7b7ce8ac80a705))
20
+ * **MU2E2-219:** New method for membership upgrade ([0548f25](https://github.com/railroadmedia/musora-content-services/commit/0548f2531dd67abda63c0768ae0005448a27c163))
21
+ * **MU2E2-219:** New method for membership upgrade ([42f2cd8](https://github.com/railroadmedia/musora-content-services/commit/42f2cd825e70a9afeb9f13bd09a0709c003b3c26))
22
+
23
+
24
+ ### Bug Fixes
25
+
26
+ * **agi:** interface return types ([cc0cfae](https://github.com/railroadmedia/musora-content-services/commit/cc0cfae1282266567ac46a6eb072f76ffde7032e))
27
+ * **BR-330:** Wraps artists name in double quotes where its interpolated in the query ([8787399](https://github.com/railroadmedia/musora-content-services/commit/8787399e032d3522e5126ea9506f28cc5cdac22a))
28
+ * collection type check ([#619](https://github.com/railroadmedia/musora-content-services/issues/619)) ([df520a4](https://github.com/railroadmedia/musora-content-services/commit/df520a497c24091b41d207992a8a71daf0fc98e5))
29
+ * duplicate awards from wrong collection type handling ([#627](https://github.com/railroadmedia/musora-content-services/issues/627)) ([f6dfbf7](https://github.com/railroadmedia/musora-content-services/commit/f6dfbf778ad8e7d37d8e0f66ecd1aa5bec323330))
30
+ * make agi responses standard ([#630](https://github.com/railroadmedia/musora-content-services/issues/630)) ([0301133](https://github.com/railroadmedia/musora-content-services/commit/03011331cb835412af80111a97e6ae83fd6e56d5))
31
+ * method progress card cta ([#622](https://github.com/railroadmedia/musora-content-services/issues/622)) ([6788b48](https://github.com/railroadmedia/musora-content-services/commit/6788b48353d4122e1ca674a5fdd32abbfa8bb642))
32
+ * **onboarding:** update hard-coded data ([e33f309](https://github.com/railroadmedia/musora-content-services/commit/e33f309d0b051829e58f631f4b1368501bafc72b))
33
+ * show next learning path lesson logic for fetch learning path lessons ([#626](https://github.com/railroadmedia/musora-content-services/issues/626)) ([2925a5b](https://github.com/railroadmedia/musora-content-services/commit/2925a5be42715af7f77720209ef78f118ae95bf4))
34
+ * watermelon fixes round [#4](https://github.com/railroadmedia/musora-content-services/issues/4) ([#621](https://github.com/railroadmedia/musora-content-services/issues/621)) ([aa1e834](https://github.com/railroadmedia/musora-content-services/commit/aa1e834dbb287e4b581b67690038e086eb7a4d55))
35
+
5
36
  ## [2.97.0](https://github.com/railroadmedia/musora-content-services/compare/v2.96.2...v2.97.0) (2025-12-09)
6
37
 
7
38
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.97.0",
3
+ "version": "2.99.0",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -6,21 +6,19 @@ export const AWSUrl = 'https://s3.us-east-1.amazonaws.com/musora-web-platform'
6
6
  export const CloudFrontURl = 'https://d3fzm1tzeyr5n3.cloudfront.net'
7
7
 
8
8
  // This is used to pull related content by license, so we only show "consumable" content
9
- export const SONG_TYPES = ['song', 'play-along', 'jam-track', 'song-tutorial-children']
9
+ export const SONG_TYPES = ['song', 'play-along', 'jam-track', 'song-tutorial-lesson']
10
10
  // Oct 2025: It turns out content-meta categories are not really clear
11
11
  // THis is used for the page_type field as a post processor so we include parents and children
12
12
  // Duplicated in SanityGateway.php if you update this, update that
13
13
  export const SONG_TYPES_WITH_CHILDREN = [
14
14
  'song',
15
- 'song-part',
16
15
  'play-along',
17
- 'play-along-part',
18
16
  'jam-track',
19
17
  'song-tutorial',
20
- 'song-tutorial-children',
18
+ 'song-tutorial-lesson',
21
19
  ]
22
20
  // Single hierarchy refers to only one element in the hierarchy has video lessons, not that they have a single parent
23
- export const SINGLE_PARENT_TYPES = ['course-part', 'pack-bundle-lesson', 'song-tutorial-children']
21
+ export const SINGLE_PARENT_TYPES = ['course-lesson', 'pack-bundle-lesson', 'song-tutorial-lesson']
24
22
 
25
23
  export const genreField = `genre[]->{
26
24
  name,
@@ -175,7 +173,7 @@ export const showsTypes = {
175
173
 
176
174
  export const coachLessonsTypes = [
177
175
  'course',
178
- 'course-part',
176
+ 'course-lesson',
179
177
  'coach-stream',
180
178
  'student-focus',
181
179
  'quick-tips',
@@ -183,7 +181,7 @@ export const coachLessonsTypes = [
183
181
  'semester-pack',
184
182
  'question-and-answer',
185
183
  'song-tutorial',
186
- 'song-tutorial-children',
184
+ 'song-tutorial-lesson',
187
185
  'workout',
188
186
  ]
189
187
 
@@ -192,15 +190,8 @@ export const childContentTypeConfig = {
192
190
  }
193
191
 
194
192
  export const singleLessonTypes = ['quick-tips', 'rudiment']
195
- export const practiceAlongsLessonTypes = ['workout'] // challenges ->workouts
193
+ export const practiceAlongsLessonTypes = ['workout']
196
194
  export const performancesLessonTypes = ['performance']
197
- export const documentariesLessonTypes = [
198
- 'tama',
199
- 'sonor',
200
- 'history-of-electronic-drums',
201
- 'paiste-cymbals',
202
- 'backstage-secret',
203
- ]
204
195
  export const liveArchivesLessonTypes = [
205
196
  'podcast',
206
197
  'coach-stream',
@@ -235,16 +226,18 @@ export const skillLessonTypes = ['skill-pack']
235
226
 
236
227
  export const showsLessonTypes = [
237
228
  'boot-camp',
238
- 'diy-drum-experiment',
239
- 'exploring-beats',
240
- 'in-rhythm',
241
- 'rhythmic-adventures-of-captain-carson',
242
- 'rhythms-from-another-planet',
243
229
  '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',
244
237
  ]
245
238
  export const entertainmentLessonTypes = [
246
- 'specials', // TODO: new type
247
- ...documentariesLessonTypes,
239
+ 'special',
240
+ 'documentary-lesson',
248
241
  ...showsLessonTypes,
249
242
  ]
250
243
  export const collectionLessonTypes = [...coursesLessonTypes, ...showsLessonTypes]
@@ -255,7 +248,7 @@ export const lessonTypesMapping = {
255
248
  'live archives': liveArchivesLessonTypes,
256
249
  performances: performancesLessonTypes,
257
250
  'student archives': studentArchivesLessonTypes,
258
- documentaries: documentariesLessonTypes,
251
+ documentaries: ['documentary-lesson'],
259
252
  courses: ['course'],
260
253
  'guided courses': ['guided-course'],
261
254
  'tiered courses': ['tiered-course'],
@@ -296,20 +289,20 @@ export const progressTypesMapping = {
296
289
  ...liveArchivesLessonTypes,
297
290
  ...performancesLessonTypes,
298
291
  ...studentArchivesLessonTypes,
299
- ...documentariesLessonTypes,
292
+ 'documentary-lesson',
300
293
  'live',
301
294
  'pack-bundle-lesson',
302
295
  ],
303
296
  course: ['course'],
304
297
  show: showsLessonTypes,
305
- 'song tutorial': [...tutorialsLessonTypes, 'song-tutorial-children'],
298
+ 'song tutorial': [...tutorialsLessonTypes, 'song-tutorial-lesson'],
306
299
  songs: transcriptionsLessonTypes,
307
300
  'play along': playAlongLessonTypes,
308
301
  'guided course': ['guided-course'],
309
302
  pack: ['pack', 'semester-pack'],
310
303
  'learning path': ['learning-path-v2'],
311
304
  'jam track': jamTrackLessonTypes,
312
- 'course video': ['course-part'],
305
+ 'course video': ['course-lesson'],
313
306
  }
314
307
 
315
308
  export const songs = {
@@ -341,9 +334,9 @@ export const filterTypes = {
341
334
  export const recentTypes = {
342
335
  lessons: [
343
336
  ...individualLessonsTypes,
344
- 'course-part',
337
+ 'course-lesson',
345
338
  'pack-bundle-lesson',
346
- 'guided-course-part',
339
+ 'guided-course-lesson',
347
340
  'quick-tips',
348
341
  ],
349
342
  songs: [...SONG_TYPES],
@@ -420,7 +413,7 @@ export let contentTypeConfig = {
420
413
  },
421
414
  },
422
415
  },
423
- 'song-tutorial-children': {
416
+ 'song-tutorial-lesson': {
424
417
  fields: [`"resources": ${resourcesField}`],
425
418
  },
426
419
  'guided-course': {
@@ -633,7 +626,7 @@ export let contentTypeConfig = {
633
626
  live: { ...contentWithInstructorsField, slug: 'live-streams' },
634
627
  solo: { ...contentWithInstructorsField, slug: 'solos' },
635
628
  'boot-camp': contentWithInstructorsField,
636
- 'gear-guids': contentWithInstructorsField,
629
+ 'gear-guide': contentWithInstructorsField,
637
630
  performance: contentWithInstructorsField,
638
631
  challenges: contentWithInstructorsField,
639
632
  'on-the-road': contentWithInstructorsField,
@@ -67,6 +67,7 @@ export class FilterBuilder {
67
67
 
68
68
  if (this.debug) console.log('baseFilter', this.filter)
69
69
  const filter = this._applyContentStatuses()
70
+ ._removeDeprecatedContent()
70
71
  ._applyPermissions()
71
72
  ._applyPublishingDateRestrictions()
72
73
  ._trimAmpersands().filter // just in case
@@ -83,6 +84,13 @@ export class FilterBuilder {
83
84
  return new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 1)
84
85
  }
85
86
 
87
+ _removeDeprecatedContent() {
88
+ this._andWhere(
89
+ `!defined(${this.prefix}deprecated_railcontent_id)`
90
+ )
91
+ return this
92
+ }
93
+
86
94
  _applyContentStatuses() {
87
95
  // This must be run before _applyPublishDateRestrictions()
88
96
  if (this.bypassStatuses) return this
package/src/index.d.ts CHANGED
@@ -352,6 +352,7 @@ import {
352
352
  import {
353
353
  fetchMemberships,
354
354
  fetchRechargeTokens,
355
+ getUpgradePrice,
355
356
  restorePurchases,
356
357
  upgradeSubscription
357
358
  } from './services/user/memberships.ts';
@@ -620,6 +621,7 @@ declare module 'musora-content-services' {
620
621
  getTabResults,
621
622
  getTimeRemainingUntilLocal,
622
623
  getToday,
624
+ getUpgradePrice,
623
625
  getUserData,
624
626
  getUserMonthlyStats,
625
627
  getUserSignature,
package/src/index.js CHANGED
@@ -356,6 +356,7 @@ import {
356
356
  import {
357
357
  fetchMemberships,
358
358
  fetchRechargeTokens,
359
+ getUpgradePrice,
359
360
  restorePurchases,
360
361
  upgradeSubscription
361
362
  } from './services/user/memberships.ts';
@@ -619,6 +620,7 @@ export {
619
620
  getTabResults,
620
621
  getTimeRemainingUntilLocal,
621
622
  getToday,
623
+ getUpgradePrice,
622
624
  getUserData,
623
625
  getUserMonthlyStats,
624
626
  getUserSignature,
@@ -218,3 +218,35 @@ export async function restorePurchases(
218
218
  requestBody
219
219
  )
220
220
  }
221
+
222
+ /**
223
+ * Get the upgrade price from Basic to Plus membership.
224
+ * Returns the price based on the user's subscription interval.
225
+ *
226
+ * For monthly subscribers: Returns the monthly upgrade cost (difference between Plus and Base monthly prices, ~$5/month)
227
+ * For yearly subscribers: Returns the monthly equivalent upgrade cost ($3.33/month from $40/year)
228
+ * For lifetime subscribers: Returns the annual upgrade cost for songs add-on ($40/year)
229
+ * If interval cannot be determined: Defaults to monthly price
230
+ *
231
+ * @returns {Promise<{price: number, currency: string, period: string|null}>} - The upgrade price information
232
+ * @property {number} price - The upgrade cost in USD (monthly for month/year, annual for lifetime)
233
+ * @property {string} currency - The currency
234
+ * @property {string|null} period - The billing period for the price ('month' or 'year'). Note: lifetime subscribers return 'year' period with annual price
235
+ *
236
+ * @example
237
+ * getUpgradePrice()
238
+ * .then(info => {
239
+ * console.log(`Upgrade price: $${info.price} per ${info.period}`)
240
+ * // Example outputs:
241
+ * // Monthly: "Upgrade price: $5 per month"
242
+ * // Yearly: "Upgrade price: $3.33 per month"
243
+ * // Lifetime: "Upgrade price: $40 per year"
244
+ * })
245
+ * .catch(error => {
246
+ * console.error('Failed to fetch upgrade price:', error)
247
+ * })
248
+ */
249
+ export async function getUpgradePrice() {
250
+ const httpClient = new HttpClient(globalConfig.baseUrl)
251
+ return httpClient.get(`${baseUrl}/v1/upgrade-price`)
252
+ }
@@ -922,7 +922,7 @@ async function extractPinnedItemsAndSortAllItems(
922
922
  }
923
923
 
924
924
  function generateContentsMap(contents, playlistsContents) {
925
- const excludedTypes = new Set(['pack-bundle', 'guided-course-part'])
925
+ const excludedTypes = new Set(['pack-bundle', 'guided-course-lesson'])
926
926
  const existingShows = new Set()
927
927
  const contentsMap = new Map()
928
928
  const childToParentMap = {}
@@ -1097,7 +1097,8 @@ async function processContentItem(content) {
1097
1097
  const progressTimestamp = content.progressTimestamp
1098
1098
  const wasPinned = content.pinned ?? false
1099
1099
  if (content.progressStatus === 'completed') {
1100
- // this could be handled more gracefully if their was a parent content type for shows
1100
+ // this could be handled more gracefully if there was a parent content type for shows
1101
+ // Update Dec 3rd. We updated almost everything to the DocumentaryType :D, but there's still a few
1101
1102
  const nextByProgress = findIncompleteLesson(progressOnItems, content.id, content.type)
1102
1103
  content = shows.find((lesson) => lesson.id === nextByProgress)
1103
1104
  content.completed_children = completedShows
@@ -1,9 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(rg:*)",
5
- "Bash(npm run lint:*)"
6
- ],
7
- "deny": []
8
- }
9
- }