musora-content-services 2.97.0 → 2.98.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.
Files changed (138) hide show
  1. package/.claude/settings.local.json +8 -3
  2. package/.coderabbit.yaml +0 -0
  3. package/.editorconfig +0 -0
  4. package/.github/pull_request_template.md +0 -0
  5. package/.github/workflows/conventional-commits.yaml +0 -0
  6. package/.github/workflows/docs.js.yml +0 -0
  7. package/.github/workflows/node.js.yml +0 -0
  8. package/.prettierignore +0 -0
  9. package/.prettierrc +0 -0
  10. package/.yarnrc.yml +1 -0
  11. package/CHANGELOG.md +24 -0
  12. package/README.md +0 -0
  13. package/jest.config.js +0 -0
  14. package/package.json +1 -1
  15. package/src/contentMetaData.js +0 -0
  16. package/src/index.d.ts +2 -0
  17. package/src/index.js +2 -0
  18. package/src/infrastructure/http/HttpClient.ts +0 -0
  19. package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
  20. package/src/infrastructure/http/index.ts +0 -0
  21. package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
  22. package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
  23. package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
  24. package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
  25. package/src/infrastructure/http/interfaces/RequestOptions.ts +0 -0
  26. package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
  27. package/src/lib/brands.ts +0 -0
  28. package/src/lib/httpHelper.js +0 -0
  29. package/src/lib/lastUpdated.js +0 -0
  30. package/src/services/api/types.js +0 -0
  31. package/src/services/api/types.ts +0 -0
  32. package/src/services/content/content.ts +0 -0
  33. package/src/services/content-org/content-org.js +0 -0
  34. package/src/services/content-org/guided-courses.ts +0 -0
  35. package/src/services/content-org/playlists-types.js +0 -0
  36. package/src/services/content-org/playlists.js +0 -0
  37. package/src/services/content.js +0 -0
  38. package/src/services/contentLikes.js +0 -0
  39. package/src/services/dataContext.js +0 -0
  40. package/src/services/dateUtils.js +0 -0
  41. package/src/services/eventsAPI.js +0 -0
  42. package/src/services/forums/categories.ts +0 -0
  43. package/src/services/forums/forums.ts +0 -0
  44. package/src/services/forums/posts.ts +0 -0
  45. package/src/services/forums/threads.ts +0 -0
  46. package/src/services/forums/types.ts +0 -0
  47. package/src/services/gamification/gamification.js +0 -0
  48. package/src/services/imageSRCBuilder.js +0 -0
  49. package/src/services/imageSRCVerify.js +0 -0
  50. package/src/services/liveTesting.ts +0 -0
  51. package/src/services/permissions/PermissionsAdapter.ts +0 -0
  52. package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
  53. package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
  54. package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
  55. package/src/services/permissions/README.md +0 -0
  56. package/src/services/permissions/index.ts +0 -0
  57. package/src/services/railcontent.js +0 -0
  58. package/src/services/recommendations.js +0 -0
  59. package/src/services/reporting/README.md +0 -0
  60. package/src/services/reporting/reporting.ts +0 -0
  61. package/src/services/reporting/types.ts +0 -0
  62. package/src/services/sentry/.indexignore +0 -0
  63. package/src/services/sentry/index.ts +0 -0
  64. package/src/services/sync/.indexignore +0 -0
  65. package/src/services/sync/adapters/factory.ts +0 -0
  66. package/src/services/sync/adapters/lokijs.ts +0 -0
  67. package/src/services/sync/adapters/sqlite.ts +0 -0
  68. package/src/services/sync/concurrency-safety.ts +0 -0
  69. package/src/services/sync/context/index.ts +0 -0
  70. package/src/services/sync/context/providers/base.ts +0 -0
  71. package/src/services/sync/context/providers/connectivity.ts +0 -0
  72. package/src/services/sync/context/providers/durability.ts +0 -0
  73. package/src/services/sync/context/providers/index.ts +0 -0
  74. package/src/services/sync/context/providers/session.ts +0 -0
  75. package/src/services/sync/context/providers/tabs.ts +0 -0
  76. package/src/services/sync/context/providers/visibility.ts +0 -0
  77. package/src/services/sync/database/factory.ts +0 -0
  78. package/src/services/sync/errors/boundary.ts +0 -0
  79. package/src/services/sync/errors/index.ts +0 -0
  80. package/src/services/sync/index.ts +0 -0
  81. package/src/services/sync/models/Base.ts +0 -0
  82. package/src/services/sync/models/ContentLike.ts +0 -0
  83. package/src/services/sync/models/Practice.ts +0 -0
  84. package/src/services/sync/models/PracticeDayNote.ts +0 -0
  85. package/src/services/sync/repositories/base.ts +0 -0
  86. package/src/services/sync/repositories/content-likes.ts +0 -0
  87. package/src/services/sync/repositories/practice-day-notes.ts +0 -0
  88. package/src/services/sync/resolver.ts +0 -0
  89. package/src/services/sync/run-scope.ts +0 -0
  90. package/src/services/sync/serializers/index.ts +0 -0
  91. package/src/services/sync/serializers/model.ts +0 -0
  92. package/src/services/sync/serializers/raw.ts +0 -0
  93. package/src/services/sync/strategies/base.ts +0 -0
  94. package/src/services/sync/strategies/index.ts +0 -0
  95. package/src/services/sync/strategies/initial.ts +0 -0
  96. package/src/services/sync/strategies/polling.ts +0 -0
  97. package/src/services/sync/telemetry/index.ts +0 -0
  98. package/src/services/sync/telemetry/sampling.ts +0 -0
  99. package/src/services/sync/utils/event-emitter.ts +0 -0
  100. package/src/services/sync/utils/index.ts +0 -0
  101. package/src/services/sync/utils/throttle.ts +0 -0
  102. package/src/services/sync/utils/timers.ts +0 -0
  103. package/src/services/types.js +0 -0
  104. package/src/services/user/account.ts +0 -0
  105. package/src/services/user/chat.js +0 -0
  106. package/src/services/user/interests.js +0 -0
  107. package/src/services/user/management.js +0 -0
  108. package/src/services/user/memberships.ts +32 -0
  109. package/src/services/user/notifications.js +0 -0
  110. package/src/services/user/payments.ts +0 -0
  111. package/src/services/user/permissions.js +0 -0
  112. package/src/services/user/profile.js +0 -0
  113. package/src/services/user/sessions.js +0 -0
  114. package/src/services/user/types.d.ts +0 -0
  115. package/src/services/user/types.js +0 -0
  116. package/src/services/user/user-management-system.js +0 -0
  117. package/test/content.test.js +0 -0
  118. package/test/contentLikes.test.js +0 -0
  119. package/test/contentProgress.test.js +0 -0
  120. package/test/dataContext.test.js +0 -0
  121. package/test/forum.test.js +0 -0
  122. package/test/imageSRCBuilder.test.js +0 -0
  123. package/test/imageSRCVerify.test.js +0 -0
  124. package/test/lib/lastUpdated.test.js +0 -0
  125. package/test/live/contentProgressLive.test.js +0 -0
  126. package/test/live/railcontentLive.test.js +0 -0
  127. package/test/localStorageMock.js +0 -0
  128. package/test/log.js +0 -0
  129. package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
  130. package/test/mockData/mockData_progress_content.json +0 -0
  131. package/test/mockData/mockData_sanity_progress_content.json +0 -0
  132. package/test/mockData/mockData_user_practices.json +0 -0
  133. package/test/notifications.test.js +0 -0
  134. package/test/progressRows.test.js +0 -0
  135. package/test/reporting.test.js +132 -0
  136. package/test/streakMessage.test.js +0 -0
  137. package/test/user/permissions.test.js +0 -0
  138. package/test/userActivity.test.js +0 -0
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
- "Bash(rg:*)",
5
- "Bash(npm run lint:*)"
4
+ "Read(//app/musora-platform-backend/**)",
5
+ "Read(//app/musora-platform-frontend/**)",
6
+ "Bash(find:*)",
7
+ "Bash(sed:*)",
8
+ "Read(//app/**)",
9
+ "Bash(cat:*)"
6
10
  ],
7
- "deny": []
11
+ "deny": [],
12
+ "ask": []
8
13
  }
9
14
  }
package/.coderabbit.yaml CHANGED
File without changes
package/.editorconfig CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
package/.prettierignore CHANGED
File without changes
package/.prettierrc CHANGED
File without changes
package/.yarnrc.yml ADDED
@@ -0,0 +1 @@
1
+ nodeLinker: node-modules
package/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
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.98.0](https://github.com/railroadmedia/musora-content-services/compare/v2.94.7...v2.98.0) (2025-12-09)
6
+
7
+
8
+ ### Features
9
+
10
+ * **BEH-1195:** Awards System ([#606](https://github.com/railroadmedia/musora-content-services/issues/606)) ([a6ffd92](https://github.com/railroadmedia/musora-content-services/commit/a6ffd92ae518c8e530d4ef743f2649725fddb285))
11
+ * **BEH-1458:** method addcontexttocontent ([#633](https://github.com/railroadmedia/musora-content-services/issues/633)) ([95a2b0a](https://github.com/railroadmedia/musora-content-services/commit/95a2b0ae3f011e17f92b78ad4fcd1ebe7a2342ca))
12
+ * 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))
13
+ * **MU2E2-219:** New method for membership upgrade ([0548f25](https://github.com/railroadmedia/musora-content-services/commit/0548f2531dd67abda63c0768ae0005448a27c163))
14
+ * **MU2E2-219:** New method for membership upgrade ([42f2cd8](https://github.com/railroadmedia/musora-content-services/commit/42f2cd825e70a9afeb9f13bd09a0709c003b3c26))
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **agi:** interface return types ([cc0cfae](https://github.com/railroadmedia/musora-content-services/commit/cc0cfae1282266567ac46a6eb072f76ffde7032e))
20
+ * **BR-330:** Wraps artists name in double quotes where its interpolated in the query ([8787399](https://github.com/railroadmedia/musora-content-services/commit/8787399e032d3522e5126ea9506f28cc5cdac22a))
21
+ * collection type check ([#619](https://github.com/railroadmedia/musora-content-services/issues/619)) ([df520a4](https://github.com/railroadmedia/musora-content-services/commit/df520a497c24091b41d207992a8a71daf0fc98e5))
22
+ * 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))
23
+ * make agi responses standard ([#630](https://github.com/railroadmedia/musora-content-services/issues/630)) ([0301133](https://github.com/railroadmedia/musora-content-services/commit/03011331cb835412af80111a97e6ae83fd6e56d5))
24
+ * method progress card cta ([#622](https://github.com/railroadmedia/musora-content-services/issues/622)) ([6788b48](https://github.com/railroadmedia/musora-content-services/commit/6788b48353d4122e1ca674a5fdd32abbfa8bb642))
25
+ * **onboarding:** update hard-coded data ([e33f309](https://github.com/railroadmedia/musora-content-services/commit/e33f309d0b051829e58f631f4b1368501bafc72b))
26
+ * 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))
27
+ * 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))
28
+
5
29
  ## [2.97.0](https://github.com/railroadmedia/musora-content-services/compare/v2.96.2...v2.97.0) (2025-12-09)
6
30
 
7
31
 
package/README.md CHANGED
File without changes
package/jest.config.js CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.97.0",
3
+ "version": "2.98.0",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
File without changes
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,
File without changes
File without changes
File without changes
package/src/lib/brands.ts CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -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
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/test/log.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Tests for Reporting Service
3
+ *
4
+ * Note: These tests use mocked HTTP calls. For integration tests,
5
+ * ensure the backend API is running at the configured baseUrl.
6
+ */
7
+
8
+ import { initializeTestService } from './initializeTests.js'
9
+ import {
10
+ reportContent,
11
+ reportForumPost,
12
+ submitReport
13
+ } from '../src/services/reporting/reporting.ts'
14
+
15
+ // Mock HttpClient to avoid actual API calls in tests
16
+ jest.mock('../src/infrastructure/http/HttpClient', () => {
17
+ return {
18
+ HttpClient: jest.fn().mockImplementation(() => ({
19
+ post: jest.fn().mockResolvedValue({
20
+ report_id: 12345,
21
+ message: 'Report submitted successfully',
22
+ is_duplicate: false
23
+ })
24
+ }))
25
+ }
26
+ })
27
+
28
+ describe('Reporting Service', () => {
29
+ beforeEach(() => {
30
+ initializeTestService()
31
+ })
32
+
33
+ describe('reportContent', () => {
34
+ test('should submit a content report with video_not_working category', async () => {
35
+ const result = await reportContent({
36
+ contentId: 123,
37
+ category: 'video_not_working',
38
+ description: 'Video freezes at 2:30'
39
+ })
40
+
41
+ expect(result).toBeDefined()
42
+ expect(result.report_id).toBe(12345)
43
+ expect(result.message).toBe('Report submitted successfully')
44
+ expect(result.is_duplicate).toBe(false)
45
+ })
46
+
47
+ test('should submit a content report without description', async () => {
48
+ const result = await reportContent({
49
+ contentId: 456,
50
+ category: 'incorrect_content'
51
+ })
52
+
53
+ expect(result).toBeDefined()
54
+ expect(result.report_id).toBeDefined()
55
+ })
56
+
57
+ test('should submit a content report with other category and description', async () => {
58
+ const result = await reportContent({
59
+ contentId: 789,
60
+ category: 'other',
61
+ description: 'Audio quality is very poor'
62
+ })
63
+
64
+ expect(result).toBeDefined()
65
+ expect(result.report_id).toBeDefined()
66
+ expect(result.message).toBeDefined()
67
+ })
68
+ })
69
+
70
+ describe('reportForumPost', () => {
71
+ test('should submit a forum post report with required brand', async () => {
72
+ const result = await reportForumPost({
73
+ postId: 555,
74
+ brand: 'drumeo',
75
+ category: 'spam'
76
+ })
77
+
78
+ expect(result).toBeDefined()
79
+ expect(result.report_id).toBeDefined()
80
+ })
81
+
82
+ test('should submit a forum post report with description', async () => {
83
+ const result = await reportForumPost({
84
+ postId: 666,
85
+ brand: 'pianote',
86
+ category: 'harassment',
87
+ description: 'User is harassing other members'
88
+ })
89
+
90
+ expect(result).toBeDefined()
91
+ expect(result.report_id).toBeDefined()
92
+ expect(result.message).toBeDefined()
93
+ })
94
+ })
95
+
96
+ describe('submitReport', () => {
97
+ test('should submit a generic report for content', async () => {
98
+ const result = await submitReport({
99
+ reportableType: 'content',
100
+ reportableId: 999,
101
+ category: 'technical_issue',
102
+ description: 'Page not loading'
103
+ })
104
+
105
+ expect(result).toBeDefined()
106
+ expect(result.report_id).toBeDefined()
107
+ })
108
+
109
+ test('should submit a generic report for playlist', async () => {
110
+ const result = await submitReport({
111
+ reportableType: 'playlist',
112
+ reportableId: 777,
113
+ category: 'incorrect_content'
114
+ })
115
+
116
+ expect(result).toBeDefined()
117
+ expect(result.report_id).toBeDefined()
118
+ })
119
+
120
+ test('should submit a generic report for comment', async () => {
121
+ const result = await submitReport({
122
+ reportableType: 'comment',
123
+ reportableId: 888,
124
+ category: 'inappropriate',
125
+ description: 'Comment contains offensive language'
126
+ })
127
+
128
+ expect(result).toBeDefined()
129
+ expect(result.report_id).toBeDefined()
130
+ })
131
+ })
132
+ })
File without changes
File without changes
File without changes