musora-content-services 2.117.8 → 2.118.1
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/.claude/settings.local.json +16 -0
- package/.coderabbit.yaml +0 -0
- package/.editorconfig +0 -0
- package/.github/pull_request_template.md +0 -0
- package/.github/workflows/conventional-commits.yaml +0 -0
- package/.github/workflows/docs.js.yml +0 -0
- package/.github/workflows/node.js.yml +0 -0
- package/.prettierignore +0 -0
- package/.prettierrc +0 -0
- package/.yarnrc.yml +1 -0
- package/CHANGELOG.md +45 -0
- package/CLAUDE.md +0 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- package/check_content.js +30 -0
- package/check_content.mjs +32 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/constants/award-assets.js +0 -0
- package/src/constants/membership-permissions.ts +0 -0
- package/src/contentMetaData.js +9 -5
- package/src/filterBuilder.js +0 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +2 -0
- package/src/infrastructure/http/HttpClient.ts +0 -0
- package/src/infrastructure/http/executors/FetchRequestExecutor.ts +0 -0
- package/src/infrastructure/http/index.ts +0 -0
- package/src/infrastructure/http/interfaces/HeaderProvider.ts +0 -0
- package/src/infrastructure/http/interfaces/HttpError.ts +0 -0
- package/src/infrastructure/http/interfaces/NetworkError.ts +0 -0
- package/src/infrastructure/http/interfaces/RequestExecutor.ts +0 -0
- package/src/infrastructure/http/providers/DefaultHeaderProvider.ts +0 -0
- package/src/lib/ads/monoid.ts +0 -0
- package/src/lib/ads/semigroup.ts +0 -0
- package/src/lib/brands.ts +0 -0
- package/src/lib/lastUpdated.js +0 -0
- package/src/lib/sanity/filter.ts +0 -0
- package/src/lib/sanity/query.ts +0 -0
- package/src/services/api/types.js +0 -0
- package/src/services/api/types.ts +0 -0
- package/src/services/awards/award-callbacks.js +0 -0
- package/src/services/awards/award-query.js +0 -0
- package/src/services/awards/internal/.indexignore +0 -0
- package/src/services/awards/internal/award-definitions.js +0 -0
- package/src/services/awards/internal/award-events.js +0 -0
- package/src/services/awards/internal/award-manager.js +0 -0
- package/src/services/awards/internal/certificate-builder.js +0 -0
- package/src/services/awards/internal/completion-data-generator.js +0 -0
- package/src/services/awards/internal/content-progress-observer.js +0 -0
- package/src/services/awards/internal/image-utils.js +0 -0
- package/src/services/awards/internal/message-generator.js +0 -0
- package/src/services/awards/internal/types.js +0 -0
- package/src/services/awards/types.d.ts +0 -0
- package/src/services/awards/types.js +0 -0
- package/src/services/content/artist.ts +0 -0
- package/src/services/content/content.ts +0 -0
- package/src/services/content/genre.ts +0 -0
- package/src/services/content/instructor.ts +0 -0
- package/src/services/content-org/content-org.js +0 -0
- package/src/services/content-org/guided-courses.ts +0 -0
- package/src/services/content-org/learning-paths.ts +0 -0
- package/src/services/content-org/playlists-types.js +0 -0
- package/src/services/content-org/playlists.js +0 -0
- package/src/services/content.js +54 -15
- package/src/services/contentAggregator.js +0 -0
- package/src/services/contentLikes.js +0 -0
- package/src/services/contentProgress.js +0 -0
- package/src/services/dataContext.js +41 -0
- package/src/services/dateUtils.js +0 -0
- package/src/services/eventsAPI.js +0 -0
- package/src/services/forums/categories.ts +0 -0
- package/src/services/forums/forums.ts +0 -0
- package/src/services/forums/posts.ts +0 -0
- package/src/services/forums/threads.ts +0 -0
- package/src/services/forums/types.ts +0 -0
- package/src/services/gamification/awards.ts +0 -0
- package/src/services/gamification/gamification.js +0 -0
- package/src/services/imageSRCBuilder.js +0 -0
- package/src/services/imageSRCVerify.js +0 -0
- package/src/services/liveTesting.ts +0 -0
- package/src/services/permissions/PermissionsAdapter.ts +0 -0
- package/src/services/permissions/PermissionsAdapterFactory.ts +0 -0
- package/src/services/permissions/PermissionsV1Adapter.ts +0 -0
- package/src/services/permissions/PermissionsV2Adapter.ts +0 -0
- package/src/services/permissions/README.md +0 -0
- package/src/services/permissions/index.ts +0 -0
- package/src/services/progress-events.js +0 -0
- package/src/services/progress-row/base.js +13 -3
- package/src/services/progress-row/rows/.indexignore +0 -0
- package/src/services/progress-row/rows/content-card.js +0 -0
- package/src/services/progress-row/rows/playlist-card.js +0 -0
- package/src/services/railcontent.js +0 -0
- package/src/services/recommendations.js +5 -2
- package/src/services/reporting/README.md +0 -0
- package/src/services/reporting/reporting.ts +0 -0
- package/src/services/reporting/types.ts +0 -0
- package/src/services/sentry/.indexignore +0 -0
- package/src/services/sentry/index.ts +0 -0
- package/src/services/sync/.indexignore +0 -0
- package/src/services/sync/adapters/factory.ts +0 -0
- package/src/services/sync/adapters/lokijs.ts +0 -0
- package/src/services/sync/adapters/sqlite.ts +0 -0
- package/src/services/sync/context/index.ts +0 -0
- package/src/services/sync/context/providers/base.ts +0 -0
- package/src/services/sync/context/providers/connectivity.ts +0 -0
- package/src/services/sync/context/providers/durability.ts +0 -0
- package/src/services/sync/context/providers/index.ts +0 -0
- package/src/services/sync/context/providers/session.ts +0 -0
- package/src/services/sync/context/providers/tabs.ts +0 -0
- package/src/services/sync/context/providers/visibility.ts +0 -0
- package/src/services/sync/database/factory.ts +0 -0
- package/src/services/sync/effects/index.ts +0 -0
- package/src/services/sync/effects/logout-warning.ts +0 -0
- package/src/services/sync/errors/boundary.ts +0 -0
- package/src/services/sync/errors/index.ts +0 -0
- package/src/services/sync/errors/validators.ts +0 -0
- package/src/services/sync/fetch.ts +0 -0
- package/src/services/sync/index.ts +0 -0
- package/src/services/sync/manager.ts +0 -0
- package/src/services/sync/models/Base.ts +0 -0
- package/src/services/sync/models/ContentLike.ts +0 -0
- package/src/services/sync/models/ContentProgress.ts +0 -0
- package/src/services/sync/models/Practice.ts +0 -0
- package/src/services/sync/models/PracticeDayNote.ts +0 -0
- package/src/services/sync/models/UserAwardProgress.ts +0 -0
- package/src/services/sync/models/index.ts +0 -0
- package/src/services/sync/repositories/base.ts +0 -0
- package/src/services/sync/repositories/content-likes.ts +0 -0
- package/src/services/sync/repositories/content-progress.ts +0 -0
- package/src/services/sync/repositories/index.ts +0 -0
- package/src/services/sync/repositories/practice-day-notes.ts +0 -0
- package/src/services/sync/repositories/practices.ts +0 -0
- package/src/services/sync/repositories/user-award-progress.ts +0 -0
- package/src/services/sync/repository-proxy.ts +0 -0
- package/src/services/sync/resolver.ts +0 -0
- package/src/services/sync/retry.ts +0 -0
- package/src/services/sync/run-scope.ts +0 -0
- package/src/services/sync/schema/index.ts +0 -0
- package/src/services/sync/serializers/index.ts +0 -0
- package/src/services/sync/serializers/model.ts +0 -0
- package/src/services/sync/serializers/raw.ts +0 -0
- package/src/services/sync/store/index.ts +0 -0
- package/src/services/sync/store/push-coalescer.ts +0 -0
- package/src/services/sync/store-configs.ts +0 -0
- package/src/services/sync/strategies/base.ts +0 -0
- package/src/services/sync/strategies/index.ts +0 -0
- package/src/services/sync/strategies/initial.ts +0 -0
- package/src/services/sync/strategies/polling.ts +0 -0
- package/src/services/sync/telemetry/flood-prevention.ts +0 -0
- package/src/services/sync/telemetry/index.ts +0 -0
- package/src/services/sync/telemetry/sampling.ts +0 -0
- package/src/services/sync/utils/event-emitter.ts +0 -0
- package/src/services/sync/utils/index.ts +0 -0
- package/src/services/sync/utils/throttle.ts +0 -0
- package/src/services/sync/utils/timers.ts +0 -0
- package/src/services/urlBuilder.ts +0 -0
- package/src/services/user/account.ts +0 -0
- package/src/services/user/chat.js +0 -0
- package/src/services/user/interests.js +0 -0
- package/src/services/user/management.js +0 -0
- package/src/services/user/memberships.ts +0 -0
- package/src/services/user/notifications.js +0 -0
- package/src/services/user/onboarding.ts +0 -0
- package/src/services/user/payments.ts +0 -0
- package/src/services/user/permissions.js +0 -0
- package/src/services/user/profile.js +0 -0
- package/src/services/user/sessions.js +9 -2
- package/src/services/user/types.d.ts +0 -0
- package/src/services/user/types.js +0 -0
- package/src/services/user/user-management-system.js +0 -0
- package/src/services/userActivity.js +0 -0
- package/test/HttpClient.test.js +0 -0
- package/test/awards/award-alacarte-observer.test.js +0 -0
- package/test/awards/award-auto-refresh.test.js +0 -0
- package/test/awards/award-calculations.test.js +0 -0
- package/test/awards/award-certificate-display.test.js +0 -0
- package/test/awards/award-collection-edge-cases.test.js +0 -0
- package/test/awards/award-collection-filtering.test.js +0 -0
- package/test/awards/award-completion-flow.test.js +0 -0
- package/test/awards/award-exclusion-handling.test.js +0 -0
- package/test/awards/award-multi-lesson.test.js +0 -0
- package/test/awards/award-observer-integration.test.js +0 -0
- package/test/awards/award-query-messages.test.js +0 -0
- package/test/awards/award-user-collection.test.js +0 -0
- package/test/awards/duplicate-prevention.test.js +0 -0
- package/test/awards/helpers/completion-mock.js +0 -0
- package/test/awards/helpers/index.js +0 -0
- package/test/awards/helpers/mock-setup.js +0 -0
- package/test/awards/helpers/progress-emitter.js +0 -0
- package/test/awards/message-generator.test.js +0 -0
- package/test/content.test.js +0 -0
- package/test/contentLikes.test.js +0 -0
- package/test/contentProgress.test.js +0 -0
- package/test/dataContext.test.js +0 -0
- package/test/forum.test.js +0 -0
- package/test/imageSRCBuilder.test.js +0 -0
- package/test/imageSRCVerify.test.js +0 -0
- package/test/initializeTests.js +0 -0
- package/test/learningPaths.test.js +0 -0
- package/test/lib/__snapshots__/filter.test.ts.snap +0 -0
- package/test/lib/filter.test.ts +0 -0
- package/test/lib/lastUpdated.test.js +0 -0
- package/test/lib/query.test.ts +0 -0
- package/test/live/contentProgressLive.test.js +0 -0
- package/test/live/railcontentLive.test.js +0 -0
- package/test/log.js +0 -0
- package/test/logout.test.js +199 -0
- package/test/mockData/award-definitions.js +0 -0
- package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
- package/test/mockData/mockData_progress_content.json +0 -0
- package/test/mockData/mockData_sanity_progress_content.json +0 -0
- package/test/mockData/mockData_user_practices.json +0 -0
- package/test/notifications.test.js +0 -0
- package/test/progressRows.test.js +0 -0
- package/test/reporting.test.js +132 -0
- package/test/sanityQueryService.test.js +0 -0
- package/test/streakMessage.test.js +0 -0
- package/test/sync/adapter.ts +0 -0
- package/test/sync/initialize-sync-manager.js +0 -0
- package/test/sync/models/award-database-integration.test.js +0 -0
- package/test/user/permissions.test.js +0 -0
- package/test/userActivity.test.js +0 -0
- package/test_owned_navigate.js +74 -0
- package/tools/generate-index.cjs +0 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Read(//app/musora-platform-backend/**)",
|
|
5
|
+
"Read(//app/musora-platform-frontend/**)",
|
|
6
|
+
"Bash(find:*)",
|
|
7
|
+
"Bash(sed:*)",
|
|
8
|
+
"Read(//app/**)",
|
|
9
|
+
"Bash(cat:*)",
|
|
10
|
+
"Bash(docker exec:*)",
|
|
11
|
+
"Bash(npm config:*)"
|
|
12
|
+
],
|
|
13
|
+
"deny": [],
|
|
14
|
+
"ask": []
|
|
15
|
+
}
|
|
16
|
+
}
|
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,51 @@
|
|
|
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.118.1](https://github.com/railroadmedia/musora-content-services/compare/v2.118.0...v2.118.1) (2026-01-14)
|
|
6
|
+
|
|
7
|
+
## [2.118.0](https://github.com/railroadmedia/musora-content-services/compare/v2.107.4...v2.118.0) (2026-01-14)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* adds column and implements for hiding cards ([#679](https://github.com/railroadmedia/musora-content-services/issues/679)) ([35ac42c](https://github.com/railroadmedia/musora-content-services/commit/35ac42cebe397c557d0b197d4fab38907ca08ab7))
|
|
13
|
+
* **BEH-1421:** lesson type migrations ([#660](https://github.com/railroadmedia/musora-content-services/issues/660)) ([7f5ab7e](https://github.com/railroadmedia/musora-content-services/commit/7f5ab7e64693b51aea754e0fb13f10edbd7a7958))
|
|
14
|
+
* **BEH-1442:** old method migration + course collection updates ([#673](https://github.com/railroadmedia/musora-content-services/issues/673)) ([24dd6bf](https://github.com/railroadmedia/musora-content-services/commit/24dd6bf6a1604ef3ee639979cf2ffab5abc05a24))
|
|
15
|
+
* **BEH-1491:** proper card ordering (and hiding) on progress row ([#686](https://github.com/railroadmedia/musora-content-services/issues/686)) ([e519c35](https://github.com/railroadmedia/musora-content-services/commit/e519c352ac5e8d09a910b89fa03baf31490da102))
|
|
16
|
+
* extra data for method card ([#691](https://github.com/railroadmedia/musora-content-services/issues/691)) ([36b034c](https://github.com/railroadmedia/musora-content-services/commit/36b034c83b86f0ff825dfc00af6a6b97b793c4c6))
|
|
17
|
+
* **MU2-1323:** Add dynamic filtering to lessons/songs excluding those without avaialable content ([072a471](https://github.com/railroadmedia/musora-content-services/commit/072a471a8b37bb31fc1421375563be0b2f124beb))
|
|
18
|
+
* **MU2-1323:** Remove redundant constant ([768befd](https://github.com/railroadmedia/musora-content-services/commit/768befdf393723cb0e091605f3c7e6ef4d523a92))
|
|
19
|
+
* **MU2-1323:** Use filterTypes for get all content types ([8065100](https://github.com/railroadmedia/musora-content-services/commit/80651009fcc9dae6661b3cbaecf55d5c3585d044))
|
|
20
|
+
* **T3Ps-1324:** Rename Tiered Courses filter to Course Collections ([97efe76](https://github.com/railroadmedia/musora-content-services/commit/97efe76fff3860d769593809bea2e59fb317b528))
|
|
21
|
+
* **T3PS-1413:** homepage progress row learning path lessons need need_access flag ([#688](https://github.com/railroadmedia/musora-content-services/issues/688)) ([cde7359](https://github.com/railroadmedia/musora-content-services/commit/cde73595c76c634b711e580497e291fa074b3d51))
|
|
22
|
+
* **TP-1046:** expose error hooks ([#655](https://github.com/railroadmedia/musora-content-services/issues/655)) ([233fa10](https://github.com/railroadmedia/musora-content-services/commit/233fa1009038448c763d130ec942b9de5a49a875))
|
|
23
|
+
* Use Get requests for Sanity if query under character limit ([#694](https://github.com/railroadmedia/musora-content-services/issues/694)) ([da5c384](https://github.com/railroadmedia/musora-content-services/commit/da5c384e7f538cf7c72a3d8f742787f24a4ed570))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
### Bug Fixes
|
|
27
|
+
|
|
28
|
+
* adds methods to set/remove http token ([0a460b6](https://github.com/railroadmedia/musora-content-services/commit/0a460b6d002fb7d85c340095d62c1e92ce253d64))
|
|
29
|
+
* **auth:** await for local storage ([69ee2ca](https://github.com/railroadmedia/musora-content-services/commit/69ee2ca780c71a707dfa452ede98240f0cfe8436))
|
|
30
|
+
* **auth:** client platform header on login ([52d5927](https://github.com/railroadmedia/musora-content-services/commit/52d5927fddd79db807440cccd541c09ae8ce770a))
|
|
31
|
+
* **auth:** login data ([a1b72d8](https://github.com/railroadmedia/musora-content-services/commit/a1b72d8145e230cfc850e208f147080c7ef8c6df))
|
|
32
|
+
* **BEH-878:** correct brand song type names ([#695](https://github.com/railroadmedia/musora-content-services/issues/695)) ([2b1cde9](https://github.com/railroadmedia/musora-content-services/commit/2b1cde9978dd744129bd906aff3a9bb03e01b04e))
|
|
33
|
+
* change js import to ts ([#683](https://github.com/railroadmedia/musora-content-services/issues/683)) ([1285cbe](https://github.com/railroadmedia/musora-content-services/commit/1285cbee851a3a2c68a0e36f37909e67173f82b8))
|
|
34
|
+
* changes lesson type mapping ([#690](https://github.com/railroadmedia/musora-content-services/issues/690)) ([af4dda9](https://github.com/railroadmedia/musora-content-services/commit/af4dda9e03eecfd49a341d2c1aea8afcf217e233))
|
|
35
|
+
* daniel merged bad ([#675](https://github.com/railroadmedia/musora-content-services/issues/675)) ([1c5863b](https://github.com/railroadmedia/musora-content-services/commit/1c5863bc921967fe16875367d9589c8dcf4e0ac3))
|
|
36
|
+
* establishes a positive progress validation ([#672](https://github.com/railroadmedia/musora-content-services/issues/672)) ([e9bc211](https://github.com/railroadmedia/musora-content-services/commit/e9bc211659262b282e1073c2746c3c8824371c35))
|
|
37
|
+
* fix explore all results ([#698](https://github.com/railroadmedia/musora-content-services/issues/698)) ([e9eb8a5](https://github.com/railroadmedia/musora-content-services/commit/e9eb8a5744b1d24c2b1b8e7ba5573cd128454463))
|
|
38
|
+
* fixes small bug with aggregator & adds safety for saveContentProgress ([#681](https://github.com/railroadmedia/musora-content-services/issues/681)) ([b3fd0a7](https://github.com/railroadmedia/musora-content-services/commit/b3fd0a7acf1fe01e2aff567148554fb291bac8a7))
|
|
39
|
+
* oops ([#693](https://github.com/railroadmedia/musora-content-services/issues/693)) ([0be66cb](https://github.com/railroadmedia/musora-content-services/commit/0be66cbaef0b33dad3074a22b9670cee4ddd0024))
|
|
40
|
+
* **pins:** user pins local storage ([#704](https://github.com/railroadmedia/musora-content-services/issues/704)) ([ca7c172](https://github.com/railroadmedia/musora-content-services/commit/ca7c1722b759c1a4711a1f6ee2213b7392d2632e))
|
|
41
|
+
* resolve foryou issue on mpf ([#703](https://github.com/railroadmedia/musora-content-services/issues/703)) ([3e8f0dd](https://github.com/railroadmedia/musora-content-services/commit/3e8f0ddc60eb51a5c510df6433e1cca1c5f5496a))
|
|
42
|
+
* Single lessons, Skill Packs and Entertainment tabs not display content and Courses display any content type ([9793443](https://github.com/railroadmedia/musora-content-services/commit/97934438bf8262fa27349eab562cecf1323c720a))
|
|
43
|
+
* some fixes from Rob ([#676](https://github.com/railroadmedia/musora-content-services/issues/676)) ([7e068ee](https://github.com/railroadmedia/musora-content-services/commit/7e068eee3cabc4de1d0620fe58eadf138532ab56))
|
|
44
|
+
* **T3PS-1187:** award progress optimizations ([#689](https://github.com/railroadmedia/musora-content-services/issues/689)) ([5d063b8](https://github.com/railroadmedia/musora-content-services/commit/5d063b8227e9ee5c70c30bc31263296bfcb4aa63))
|
|
45
|
+
* **T3PS-1289:** navigateTo calculation ([#677](https://github.com/railroadmedia/musora-content-services/issues/677)) ([12f4ca3](https://github.com/railroadmedia/musora-content-services/commit/12f4ca38b05a2175b33a9260e7c00f9aebfb8a87))
|
|
46
|
+
* **T3PS-1347:** Update getUserWeeklyStats to include query for past 60 days for streak calculation, retain original contract of the function ([d798acf](https://github.com/railroadmedia/musora-content-services/commit/d798acf2a01f25551746030722a41ccb81030ed9))
|
|
47
|
+
* **T3PS:** Cleanup ([07f057f](https://github.com/railroadmedia/musora-content-services/commit/07f057f867c8a3931ae6cbf5ecca9ae471f23d00))
|
|
48
|
+
* **TP-1051:** group contentProgress upsert pushes ([#665](https://github.com/railroadmedia/musora-content-services/issues/665)) ([27ff11f](https://github.com/railroadmedia/musora-content-services/commit/27ff11fb1b10075313e614cf895356a221f0c0d1))
|
|
49
|
+
|
|
5
50
|
### [2.117.8](https://github.com/railroadmedia/musora-content-services/compare/v2.117.7...v2.117.8) (2026-01-13)
|
|
6
51
|
|
|
7
52
|
|
package/CLAUDE.md
CHANGED
|
File without changes
|
package/README.md
CHANGED
|
File without changes
|
package/babel.config.cjs
CHANGED
|
File without changes
|
package/check_content.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const { initializeService } = require('./src/services/config.js');
|
|
2
|
+
const { fetchByRailContentIds } = require('./src/services/sanity.js');
|
|
3
|
+
require('dotenv/config');
|
|
4
|
+
|
|
5
|
+
async function checkContent() {
|
|
6
|
+
initializeService({
|
|
7
|
+
sanityConfig: {
|
|
8
|
+
token: process.env.SANITY_TOKEN,
|
|
9
|
+
projectId: process.env.SANITY_PROJECT_ID,
|
|
10
|
+
dataset: process.env.SANITY_DATASET,
|
|
11
|
+
version: process.env.SANITY_VERSION || '2021-06-07',
|
|
12
|
+
},
|
|
13
|
+
railcontentConfig: {
|
|
14
|
+
token: process.env.RAILCONTENT_TOKEN,
|
|
15
|
+
userId: process.env.RAILCONTENT_USER_ID,
|
|
16
|
+
baseUrl: process.env.RAILCONTENT_BASE_URL,
|
|
17
|
+
authToken: process.env.RAILCONTENT_AUTH_TOKEN,
|
|
18
|
+
},
|
|
19
|
+
baseUrl: process.env.RAILCONTENT_BASE_URL,
|
|
20
|
+
localStorage: null,
|
|
21
|
+
isMA: false,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log('Checking railcontent_id: 421814');
|
|
25
|
+
const contents = await fetchByRailContentIds([421814]);
|
|
26
|
+
console.log('Results:', JSON.stringify(contents, null, 2));
|
|
27
|
+
console.log('Found:', contents.length, 'items');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
checkContent().catch(console.error);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { initializeService } from './src/services/config.js';
|
|
2
|
+
import { fetchByRailContentIds } from './src/services/sanity.js';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
6
|
+
|
|
7
|
+
async function checkContent() {
|
|
8
|
+
initializeService({
|
|
9
|
+
sanityConfig: {
|
|
10
|
+
token: process.env.SANITY_TOKEN,
|
|
11
|
+
projectId: process.env.SANITY_PROJECT_ID,
|
|
12
|
+
dataset: process.env.SANITY_DATASET,
|
|
13
|
+
version: process.env.SANITY_VERSION || '2021-06-07',
|
|
14
|
+
},
|
|
15
|
+
railcontentConfig: {
|
|
16
|
+
token: process.env.RAILCONTENT_TOKEN,
|
|
17
|
+
userId: process.env.RAILCONTENT_USER_ID,
|
|
18
|
+
baseUrl: process.env.RAILCONTENT_BASE_URL,
|
|
19
|
+
authToken: process.env.RAILCONTENT_AUTH_TOKEN,
|
|
20
|
+
},
|
|
21
|
+
baseUrl: process.env.RAILCONTENT_BASE_URL,
|
|
22
|
+
localStorage: null,
|
|
23
|
+
isMA: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
console.log('Checking railcontent_id: 421814');
|
|
27
|
+
const contents = await fetchByRailContentIds([421814]);
|
|
28
|
+
console.log('Results:', JSON.stringify(contents, null, 2));
|
|
29
|
+
console.log('Found:', contents.length, 'items');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
checkContent().catch(console.error);
|
package/jsdoc.json
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
package/src/contentMetaData.js
CHANGED
|
@@ -53,7 +53,7 @@ export class Tabs {
|
|
|
53
53
|
static Collections = { name: 'Collections', short_name: 'Collections', value: 'type,collections', cardType: 'big' }
|
|
54
54
|
static ExploreAll = { name: 'Explore All', short_name: 'Explore All', value: 'tab,explore all', icon: 'icon-filters', cardType: 'big'}
|
|
55
55
|
static All = { name: 'All', short_name: 'All', value: '' }
|
|
56
|
-
static Courses = { name: 'Courses', short_name: 'Courses', value: 'type,Courses' }
|
|
56
|
+
static Courses = { name: 'Courses', short_name: 'Courses', value: 'type,Courses', recSysSection: 'lesson', }
|
|
57
57
|
static SkillLevel = { name: 'Skill Level', short_name: 'SKILL LEVEL', is_group_by: true, value: 'difficulty_string' }
|
|
58
58
|
static Genres = { name: 'Genres', short_name: 'Genres', is_group_by: true, value: 'genre' }
|
|
59
59
|
static Completed = {
|
|
@@ -82,12 +82,14 @@ export class Tabs {
|
|
|
82
82
|
short_name: 'Tutorials',
|
|
83
83
|
value: 'type,tutorials',
|
|
84
84
|
cardType: 'big',
|
|
85
|
+
recSysSection: 'song',
|
|
85
86
|
}
|
|
86
87
|
static Transcriptions = {
|
|
87
88
|
name: 'Transcriptions',
|
|
88
89
|
short_name: 'Transcriptions',
|
|
89
90
|
value: 'type,transcriptions',
|
|
90
91
|
cardType: 'small',
|
|
92
|
+
recSysSection: 'song',
|
|
91
93
|
}
|
|
92
94
|
static SheetMusic = {
|
|
93
95
|
name: 'Sheet Music',
|
|
@@ -100,12 +102,14 @@ export class Tabs {
|
|
|
100
102
|
short_name: 'Tabs',
|
|
101
103
|
value: 'type,transcriptions',
|
|
102
104
|
cardType: 'small',
|
|
105
|
+
recSysSection: 'song',
|
|
103
106
|
}
|
|
104
107
|
static PlayAlongs = {
|
|
105
108
|
name: 'Play-Alongs',
|
|
106
109
|
short_name: 'Play-Alongs',
|
|
107
|
-
value: 'type,play
|
|
110
|
+
value: 'type,play-along',
|
|
108
111
|
cardType: 'small',
|
|
112
|
+
recSysSection: 'song',
|
|
109
113
|
}
|
|
110
114
|
static JamTracks = {
|
|
111
115
|
name: 'Jam Tracks',
|
|
@@ -121,9 +125,9 @@ export class Tabs {
|
|
|
121
125
|
static RecentActivityPosts = { name: 'Posts', short_name: 'Posts' }
|
|
122
126
|
static RecentActivityComments = { name: 'Comments', short_name: 'Comments' }
|
|
123
127
|
// new tabs - 29.10
|
|
124
|
-
static SingleLessons = { name: 'Single Lessons', short_name: 'Single Lessons', value: 'type,Single Lessons' }
|
|
125
|
-
static SkillPacks = { name: 'Skill Packs', short_name: 'Skill Packs', value: 'type,Skill Packs' }
|
|
126
|
-
static Entertainment = { name: 'Entertainment', short_name: 'Entertainment', value: 'type,Entertainment' }
|
|
128
|
+
static SingleLessons = { name: 'Single Lessons', short_name: 'Single Lessons', value: 'type,Single Lessons', recSysSection: 'lesson', }
|
|
129
|
+
static SkillPacks = { name: 'Skill Packs', short_name: 'Skill Packs', value: 'type,Skill Packs', recSysSection: 'lesson', }
|
|
130
|
+
static Entertainment = { name: 'Entertainment', short_name: 'Entertainment', value: 'type,Entertainment', recSysSection: 'lesson', }
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
/**
|
package/src/filterBuilder.js
CHANGED
|
File without changes
|
package/src/index.d.ts
CHANGED
|
@@ -128,6 +128,7 @@ import {
|
|
|
128
128
|
} from './services/contentProgress.js';
|
|
129
129
|
|
|
130
130
|
import {
|
|
131
|
+
clearAllCachedData,
|
|
131
132
|
verifyLocalDataContext
|
|
132
133
|
} from './services/dataContext.js';
|
|
133
134
|
|
|
@@ -444,6 +445,7 @@ declare module 'musora-content-services' {
|
|
|
444
445
|
buildEntityAndTotalQuery,
|
|
445
446
|
buildImageSRC,
|
|
446
447
|
calculateLongestStreaks,
|
|
448
|
+
clearAllCachedData,
|
|
447
449
|
closeComment,
|
|
448
450
|
completeLearningPathIntroVideo,
|
|
449
451
|
completeMethodIntroVideo,
|
package/src/index.js
CHANGED
|
@@ -132,6 +132,7 @@ import {
|
|
|
132
132
|
} from './services/contentProgress.js';
|
|
133
133
|
|
|
134
134
|
import {
|
|
135
|
+
clearAllCachedData,
|
|
135
136
|
verifyLocalDataContext
|
|
136
137
|
} from './services/dataContext.js';
|
|
137
138
|
|
|
@@ -443,6 +444,7 @@ export {
|
|
|
443
444
|
buildEntityAndTotalQuery,
|
|
444
445
|
buildImageSRC,
|
|
445
446
|
calculateLongestStreaks,
|
|
447
|
+
clearAllCachedData,
|
|
446
448
|
closeComment,
|
|
447
449
|
completeLearningPathIntroVideo,
|
|
448
450
|
completeMethodIntroVideo,
|
|
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/src/lib/ads/monoid.ts
CHANGED
|
File without changes
|
package/src/lib/ads/semigroup.ts
CHANGED
|
File without changes
|
package/src/lib/brands.ts
CHANGED
|
File without changes
|
package/src/lib/lastUpdated.js
CHANGED
|
File without changes
|
package/src/lib/sanity/filter.ts
CHANGED
|
File without changes
|
package/src/lib/sanity/query.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
|
package/src/services/content.js
CHANGED
|
@@ -18,7 +18,10 @@ import {recommendations, rankCategories, rankItems} from "./recommendations";
|
|
|
18
18
|
import {addContextToContent} from "./contentAggregator.js";
|
|
19
19
|
import {globalConfig} from "./config";
|
|
20
20
|
import {getUserData} from "./user/management";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
lessonTypesMapping,
|
|
23
|
+
ownedContentTypes
|
|
24
|
+
} from "../contentTypeConfig";
|
|
22
25
|
import {getPermissionsAdapter} from "./permissions/index.ts";
|
|
23
26
|
import {MEMBERSHIP_PERMISSIONS} from "../constants/membership-permissions.ts";
|
|
24
27
|
|
|
@@ -100,6 +103,7 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
100
103
|
tabObj => tabObj.name.toLowerCase() === tabName.toLowerCase()
|
|
101
104
|
)
|
|
102
105
|
const tabValue = tabMatch?.value || ''
|
|
106
|
+
const tabRecSysSection = tabMatch?.recSysSection || ''
|
|
103
107
|
const mergedIncludedFields = tabValue ? [...filteredSelectedFilters, tabValue] : filteredSelectedFilters;
|
|
104
108
|
|
|
105
109
|
// Fetch data
|
|
@@ -112,23 +116,58 @@ export async function getTabResults(brand, pageName, tabName, {
|
|
|
112
116
|
addProgressPercentage: true,
|
|
113
117
|
addProgressStatus: true
|
|
114
118
|
})
|
|
119
|
+
} else if (sort === 'recommended') {
|
|
120
|
+
const contentTypes = lessonTypesMapping[tabName.toLowerCase()] || []
|
|
121
|
+
const allRecommendations = await recommendations(brand, { contentTypes, section: tabRecSysSection })
|
|
122
|
+
|
|
123
|
+
let contentToDisplay
|
|
124
|
+
if (allRecommendations.length > 0) {
|
|
125
|
+
// Fetch and sort recommended content
|
|
126
|
+
let recommendedContent = await fetchByRailContentIds(allRecommendations, 'tab-data', brand, true)
|
|
127
|
+
recommendedContent.sort((a, b) => allRecommendations.indexOf(a.id) - allRecommendations.indexOf(b.id))
|
|
128
|
+
|
|
129
|
+
const start = (page - 1) * limit
|
|
130
|
+
const end = start + limit
|
|
131
|
+
|
|
132
|
+
// Need more content beyond recommendations?
|
|
133
|
+
if (recommendedContent.length < end) {
|
|
134
|
+
const additionalNeeded = end - recommendedContent.length;
|
|
135
|
+
const tabData = await fetchTabData(brand, pageName, {
|
|
136
|
+
page: Math.ceil(additionalNeeded / limit),
|
|
137
|
+
limit: additionalNeeded + limit,
|
|
138
|
+
sort: '-published_on',
|
|
139
|
+
includedFields: mergedIncludedFields,
|
|
140
|
+
progress: progressValue
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Filter out duplicates and combine
|
|
144
|
+
const recommendedIds = new Set(recommendedContent.map(c => c.id))
|
|
145
|
+
const additionalContent = tabData.entity.filter(c => !recommendedIds.has(c.id))
|
|
146
|
+
|
|
147
|
+
contentToDisplay = [...recommendedContent, ...additionalContent].slice(start, end)
|
|
148
|
+
} else {
|
|
149
|
+
contentToDisplay = recommendedContent.slice(start, end)
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
// No recommendations - use normal flow
|
|
153
|
+
const temp = await fetchTabData(brand, pageName, { page, limit, sort: '-published_on', includedFields: mergedIncludedFields, progress: progressValue })
|
|
154
|
+
contentToDisplay = temp.entity
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
results = await addContextToContent(() => contentToDisplay, {
|
|
158
|
+
addNextLesson: true,
|
|
159
|
+
addNavigateTo: true,
|
|
160
|
+
addProgressPercentage: true,
|
|
161
|
+
addProgressStatus: true
|
|
162
|
+
})
|
|
115
163
|
} else {
|
|
116
164
|
let temp = await fetchTabData(brand, pageName, { page, limit, sort, includedFields: mergedIncludedFields, progress: progressValue });
|
|
117
165
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
addProgressPercentage: true,
|
|
124
|
-
addProgressStatus: true
|
|
125
|
-
})
|
|
126
|
-
]);
|
|
127
|
-
|
|
128
|
-
results = ranking.length === 0 ? contextResults : contextResults.sort((a, b) => {
|
|
129
|
-
const indexA = ranking.indexOf(a.id);
|
|
130
|
-
const indexB = ranking.indexOf(b.id);
|
|
131
|
-
return (indexA === -1 ? Infinity : indexA) - (indexB === -1 ? Infinity : indexB);
|
|
166
|
+
results = await addContextToContent(() => temp.entity, {
|
|
167
|
+
addNextLesson: true,
|
|
168
|
+
addNavigateTo: true,
|
|
169
|
+
addProgressPercentage: true,
|
|
170
|
+
addProgressStatus: true
|
|
132
171
|
})
|
|
133
172
|
}
|
|
134
173
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -147,3 +147,44 @@ export class DataContext {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Clears all dataContext cached data from localStorage.
|
|
153
|
+
* Should be called on logout to prevent data leakage between users.
|
|
154
|
+
* Note: Does not clear user_pin_progress_row keys as they are user-specific.
|
|
155
|
+
*/
|
|
156
|
+
export async function clearAllCachedData() {
|
|
157
|
+
const storage = globalConfig.localStorage
|
|
158
|
+
|
|
159
|
+
if (storage) {
|
|
160
|
+
const keysToRemove = []
|
|
161
|
+
|
|
162
|
+
// For React Native AsyncStorage
|
|
163
|
+
if (globalConfig.isMA && storage.getAllKeys) {
|
|
164
|
+
const allKeys = await storage.getAllKeys()
|
|
165
|
+
keysToRemove.push(...allKeys.filter(key =>
|
|
166
|
+
key.startsWith('dataContext_')
|
|
167
|
+
))
|
|
168
|
+
}
|
|
169
|
+
// For web localStorage
|
|
170
|
+
else if (typeof storage.length !== 'undefined') {
|
|
171
|
+
const allKeys = []
|
|
172
|
+
for (let i = 0; i < storage.length; i++) {
|
|
173
|
+
const key = storage.key(i)
|
|
174
|
+
if (key) {
|
|
175
|
+
allKeys.push(key)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
keysToRemove.push(...allKeys.filter(key =>
|
|
179
|
+
key.startsWith('dataContext_')
|
|
180
|
+
))
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Use multiRemove for React Native AsyncStorage, removeItem for web localStorage
|
|
184
|
+
if (storage.multiRemove && typeof storage.multiRemove === 'function') {
|
|
185
|
+
await storage.multiRemove(keysToRemove)
|
|
186
|
+
} else {
|
|
187
|
+
keysToRemove.forEach(key => storage.removeItem(key))
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
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
|
|
@@ -18,6 +18,14 @@ import { PUT } from '../../infrastructure/http/HttpClient.ts'
|
|
|
18
18
|
|
|
19
19
|
export const USER_PIN_PROGRESS_KEY = 'user_pin_progress_row'
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Gets the localStorage key for user pinned progress, scoped by user ID
|
|
23
|
+
*/
|
|
24
|
+
function getUserPinProgressKey() {
|
|
25
|
+
const userId = globalConfig.sessionConfig?.userId || globalConfig.railcontentConfig?.userId
|
|
26
|
+
return userId ? `user_pin_progress_row_${userId}` : USER_PIN_PROGRESS_KEY
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
/**
|
|
22
30
|
* Fetches and combines recent user progress rows and playlists, excluding certain types and parents.
|
|
23
31
|
*
|
|
@@ -102,7 +110,8 @@ export async function unpinProgressRow(brand) {
|
|
|
102
110
|
}
|
|
103
111
|
|
|
104
112
|
async function getUserPinnedItem(brand) {
|
|
105
|
-
const
|
|
113
|
+
const key = getUserPinProgressKey()
|
|
114
|
+
const pinnedProgressRaw = await globalConfig.localStorage.getItem(key)
|
|
106
115
|
let pinnedProgress = pinnedProgressRaw ? JSON.parse(pinnedProgressRaw) : {}
|
|
107
116
|
pinnedProgress = pinnedProgress || {}
|
|
108
117
|
return pinnedProgress[brand] ?? null
|
|
@@ -200,9 +209,10 @@ function mergeAndSortItems(items, limit) {
|
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
async function updateUserPinnedProgressRow(brand, pinnedData) {
|
|
203
|
-
const
|
|
212
|
+
const key = getUserPinProgressKey()
|
|
213
|
+
const pinnedProgressRaw = await globalConfig.localStorage.getItem(key)
|
|
204
214
|
let pinnedProgress = pinnedProgressRaw ? JSON.parse(pinnedProgressRaw) : {}
|
|
205
215
|
pinnedProgress = pinnedProgress || {}
|
|
206
216
|
pinnedProgress[brand] = pinnedData
|
|
207
|
-
await globalConfig.localStorage.setItem(
|
|
217
|
+
await globalConfig.localStorage.setItem(key, JSON.stringify(pinnedProgress))
|
|
208
218
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|