musora-content-services 1.0.114 → 1.0.116

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 (50) hide show
  1. package/.github/workflows/node.js.yml +0 -0
  2. package/CHANGELOG.md +4 -0
  3. package/README.md +0 -0
  4. package/babel.config.js +0 -0
  5. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  6. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  7. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  8. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  9. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  10. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  11. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  12. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  13. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  14. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
  15. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  16. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  17. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  18. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  19. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
  20. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  21. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  22. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  23. package/docs/scripts/collapse.js +0 -0
  24. package/docs/scripts/commonNav.js +0 -0
  25. package/docs/scripts/linenumber.js +0 -0
  26. package/docs/scripts/nav.js +0 -0
  27. package/docs/scripts/polyfill.js +0 -0
  28. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
  29. package/docs/scripts/prettify/lang-css.js +0 -0
  30. package/docs/scripts/prettify/prettify.js +0 -0
  31. package/docs/scripts/search.js +0 -0
  32. package/docs/styles/jsdoc.css +0 -0
  33. package/docs/styles/prettify.css +0 -0
  34. package/jest.config.js +0 -0
  35. package/jsdoc.json +0 -0
  36. package/link_mcs.sh +0 -0
  37. package/package.json +2 -1
  38. package/src/contentTypeConfig.js +24 -24
  39. package/src/filterBuilder.js +0 -0
  40. package/src/index.d.ts +137 -88
  41. package/src/index.js +135 -97
  42. package/src/services/config.js +0 -0
  43. package/src/services/railcontent.js +0 -0
  44. package/src/services/sanity.js +75 -23
  45. package/src/services/userContext.js +0 -0
  46. package/test/localStorageMock.js +0 -0
  47. package/test/log.js +0 -0
  48. package/test/sanityQueryService.test.js +32 -0
  49. package/test/userContext.test.js +0 -0
  50. package/tools/generate-index.js +85 -0
File without changes
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
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
+ ### [1.0.116](https://github.com/railroadmedia/musora-content-services/compare/v1.0.115...v1.0.116) (2024-09-26)
6
+
7
+ ### [1.0.115](https://github.com/railroadmedia/musora-content-services/compare/v1.0.114...v1.0.115) (2024-09-25)
8
+
5
9
  ### [1.0.114](https://github.com/railroadmedia/musora-content-services/compare/v1.0.113...v1.0.114) (2024-09-25)
6
10
 
7
11
  ### [1.0.113](https://github.com/railroadmedia/musora-content-services/compare/v1.0.112...v1.0.113) (2024-09-25)
package/README.md CHANGED
File without changes
package/babel.config.js 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
package/jest.config.js CHANGED
File without changes
package/jsdoc.json CHANGED
File without changes
package/link_mcs.sh CHANGED
File without changes
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "1.0.114",
3
+ "version": "1.0.116",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
+ "build-index": "node tools/generate-index.js",
7
8
  "release": "standard-version",
8
9
  "doc": "jsdoc -c jsdoc.json --verbose",
9
10
  "test": "jest --setupFiles dotenv/config"
@@ -54,7 +54,7 @@ const showsTypes = {
54
54
 
55
55
  const contentMetadata = {
56
56
  'drumeo': {
57
- 'coaches': {
57
+ 'instructor': {
58
58
  name: 'Coaches',
59
59
  icon: 'icon-coach',
60
60
  description: "Your drumming journey is unique. You need personalized coaching that helps you reach your goals. Learn from some of the best drummers in the world!",
@@ -65,7 +65,7 @@ const contentMetadata = {
65
65
  name: 'Courses',
66
66
  icon: 'icon-courses',
67
67
  description: "Tackle your next drumming goal with bite-sized courses from many of the world's best drummers.",
68
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'lifestyle', 'creativity'],
68
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'lifestyle', 'creativity'],
69
69
  sortBy: '-published_on',
70
70
  tabs: [
71
71
  {
@@ -117,7 +117,7 @@ const contentMetadata = {
117
117
  name: 'Student Focus',
118
118
  icon: 'icon-student-focus',
119
119
  description: "Submit your playing for personalized and direct feedback, or look at the archive to see what challenges our instructors have already addressed.",
120
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
120
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
121
121
  sortBy: '-published_on',
122
122
  tabs: [
123
123
  {
@@ -236,7 +236,7 @@ const contentMetadata = {
236
236
  name: 'Boot Camps',
237
237
  icon: 'icon-shows',
238
238
  description: "Grab your sticks and practice along while watching a lesson! These boot camps are designed like workout videos so you can follow along and push your drumming at the same time.",
239
- allowableFilters: ['difficulty', 'genre', 'essentials'],
239
+ allowableFilters: ['difficulty', 'genre', 'essential'],
240
240
  sortBy: '-published_on',
241
241
  tabs: [
242
242
  {
@@ -263,7 +263,7 @@ const contentMetadata = {
263
263
  name: 'Quick Tips',
264
264
  icon: 'icon-shows',
265
265
  description: "Only have 10 minutes? These short lessons are designed to inspire you with quick tips and exercises, even if you don’t have lots of time to practice.",
266
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'lifestyle', 'creativity'],
266
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'lifestyle', 'creativity'],
267
267
  sortBy: '-published_on',
268
268
  tabs: [
269
269
  {
@@ -327,7 +327,7 @@ const contentMetadata = {
327
327
  shortname: 'Live Lessons',
328
328
  icon: 'icon-shows',
329
329
  description: "Practice sessions, Q&A, celebrations, and more are available during Drumeo live lessons. Subscribe to an event or the whole calendar, so you don’t miss out!",
330
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory'],
330
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory'],
331
331
  sortBy: '-published_on',
332
332
  tabs: [
333
333
  {
@@ -453,7 +453,7 @@ const contentMetadata = {
453
453
  shortname: 'Lessons',
454
454
  icon: 'icon-shows',
455
455
  description: "Get any drum related question answered by a Drumeo instructor on our weekly Q&A episodes! You can submit as many questions as you like by clicking the button below, and either join us live for the next episode, or check for your answer in the archived videos below!",
456
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory'],
456
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory'],
457
457
  sortBy: '-published_on',
458
458
  },
459
459
  'student-collaboration': {
@@ -685,11 +685,11 @@ const contentMetadata = {
685
685
  ],
686
686
  },
687
687
  'pack': {
688
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'lifestyle'],
688
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'lifestyle'],
689
689
  },
690
690
  },
691
691
  'pianote':{
692
- 'coaches': {
692
+ 'instructor': {
693
693
  name: 'Coaches',
694
694
  icon: 'icon-coach',
695
695
  description: "Your piano journey is unique. You need personalized coaching that helps you reach your goals. Learn from some of the best pianists in the world!",
@@ -729,7 +729,7 @@ const contentMetadata = {
729
729
  'course': {
730
730
  name: "Courses",
731
731
  thumbnailUrl: 'https://dpwjbsxqtam5n.cloudfront.net/shows/pianote/courses.jpg',
732
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
732
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
733
733
  sortBy: '-published_on',
734
734
  shortname: 'Courses',
735
735
  icon: "icon-courses",
@@ -789,7 +789,7 @@ const contentMetadata = {
789
789
  'student-review': {
790
790
  name: 'Student Reviews',
791
791
  thumbnailUrl: 'https://dpwjbsxqtam5n.cloudfront.net/shows/pianote/student-review.jpg',
792
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
792
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
793
793
  shortname: 'Student Reviews',
794
794
  icon: 'icon-student-focus',
795
795
  description: "Want feedback on your playing? Submit a video for student review. We will watch your submission and then provide helpful encouragement and feedback. This is a great way to build accountability and benefit from the expertise of our teachers.",
@@ -819,7 +819,7 @@ const contentMetadata = {
819
819
  'question-and-answer': {
820
820
  thumbnailUrl: 'https://dpwjbsxqtam5n.cloudfront.net/shows/pianote/question-answer.jpg',
821
821
  name: 'Q&A',
822
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory'],
822
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory'],
823
823
  sortBy: '-published_on',
824
824
  shortname: 'Q&A',
825
825
  icon: 'icon-student-focus',
@@ -849,7 +849,7 @@ const contentMetadata = {
849
849
  'boot-camp': {
850
850
  thumbnailUrl: 'https://dpwjbsxqtam5n.cloudfront.net/shows/pianote/bootcamps.jpg',
851
851
  name: 'Bootcamps',
852
- allowableFilters: ['difficulty', 'genre', 'essentials'],
852
+ allowableFilters: ['difficulty', 'genre', 'essential'],
853
853
  sortBy: '-published_on',
854
854
  shortname: 'Bootcamps',
855
855
  icon: 'icon-chords-scales-icon',
@@ -991,7 +991,7 @@ const contentMetadata = {
991
991
  },
992
992
  },
993
993
  'guitareo': {
994
- 'coaches': {
994
+ 'instructor': {
995
995
  name: 'Coaches',
996
996
  icon: 'icon-coach',
997
997
  description: "Tackle your next guitar goal with bite-sized courses from many of the world's best guitarists.",
@@ -1002,7 +1002,7 @@ const contentMetadata = {
1002
1002
  name: "Courses",
1003
1003
  icon: "icon-courses",
1004
1004
  description: "These jam-packed training courses cover various lesson topics in detail. Find one that suits your guitar goals, and get started!",
1005
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
1005
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
1006
1006
  tabs: [
1007
1007
  {
1008
1008
  name: 'Courses',
@@ -1052,7 +1052,7 @@ const contentMetadata = {
1052
1052
  name: "Play Alongs",
1053
1053
  icon: "icon-play-alongs",
1054
1054
  description: "Our play-along feature teaches you chords, strumming patterns, riffs, and song layouts -- with handy playback tools to help you create the perfect performance.",
1055
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'lifestyle'],
1055
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'lifestyle'],
1056
1056
  tabs: [
1057
1057
  {
1058
1058
  name: 'All Play-Alongs',
@@ -1093,7 +1093,7 @@ const contentMetadata = {
1093
1093
  shortname: "quick-tips",
1094
1094
  icon: "icon-shows",
1095
1095
  description: "Only have 10 minutes? These short lessons are designed to inspire you with quick tips and exercises, even if you don’t have lots of time to practice.",
1096
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'lifestyle'],
1096
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'lifestyle'],
1097
1097
  tabs: [
1098
1098
  {
1099
1099
  name: 'Lessons',
@@ -1119,14 +1119,14 @@ const contentMetadata = {
1119
1119
  name: "Q&A",
1120
1120
  icon: "fas fa-question-circle",
1121
1121
  description: "Each week we go live to answer your questions. Submit your questions in advance using the button below, in the Q&A thread in the forums, or live in the community chat.",
1122
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory'],
1122
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory'],
1123
1123
  },
1124
1124
  'student-review': {
1125
1125
  thumbnailUrl: 'https://d1923uyy6spedc.cloudfront.net/student-reviews-singeo.png',
1126
1126
  name: "Student Reviews",
1127
1127
  icon: "icon-student-focus",
1128
1128
  description: "Want feedback on your playing? Submit a video for student review. We will watch your submission and then provide helpful encouragement and feedback. This is a great way to build accountability and benefit from the expertise of our teachers.",
1129
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
1129
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
1130
1130
  tabs: [
1131
1131
  {
1132
1132
  name: 'Lessons',
@@ -1202,7 +1202,7 @@ const contentMetadata = {
1202
1202
  },
1203
1203
  },
1204
1204
  'singeo':{
1205
- 'coaches': {
1205
+ 'instructor': {
1206
1206
  name: 'Coaches',
1207
1207
  icon: 'icon-coach',
1208
1208
  description: "Your singing journey is unique. You need personalized coaching that helps you reach your goals. Learn from some of the best singers and vocal coaches in the world!",
@@ -1213,7 +1213,7 @@ const contentMetadata = {
1213
1213
  name: "Courses",
1214
1214
  icon: "icon-courses",
1215
1215
  description: "Tackle your next singing goal with bite-sized courses from many of the world's best vocalists.",
1216
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
1216
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
1217
1217
  tabs: [
1218
1218
  {
1219
1219
  name: 'Courses',
@@ -1264,7 +1264,7 @@ const contentMetadata = {
1264
1264
  name: "Quick Tips",
1265
1265
  icon: "icon-shows",
1266
1266
  description: "Only have 10 minutes? These short lessons are designed to inspire you with quick tips and exercises, even if you don’t have lots of time to practice.",
1267
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
1267
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
1268
1268
  tabs: [
1269
1269
  {
1270
1270
  name: 'Lessons',
@@ -1290,7 +1290,7 @@ const contentMetadata = {
1290
1290
  name: "Q&A",
1291
1291
  icon: "fas fa-question-circle",
1292
1292
  description: "Each week we go live to answer your questions. Submit your questions in advance using the button below, in the Q&A thread in the forums, or live in the community chat.",
1293
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory'],
1293
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory'],
1294
1294
  tabs: [
1295
1295
  {
1296
1296
  name: 'Lessons',
@@ -1316,7 +1316,7 @@ const contentMetadata = {
1316
1316
  name: "Student Reviews",
1317
1317
  icon: "icon-student-focus",
1318
1318
  description: "Want feedback on your singing? Submit a video for student review. We will watch your submission and then provide helpful encouragement and feedback. This is a great way to build accountability and benefit from the expertise of our teachers.",
1319
- allowableFilters: ['difficulty', 'genre', 'essentials', 'theory', 'creativity', 'lifestyle'],
1319
+ allowableFilters: ['difficulty', 'genre', 'essential', 'theory', 'creativity', 'lifestyle'],
1320
1320
  tabs: [
1321
1321
  {
1322
1322
  name: 'Lessons',
File without changes
package/src/index.d.ts CHANGED
@@ -1,95 +1,144 @@
1
+ /*** This file was generated automatically. To recreate, please run `npm run build-index`. ***/
2
+
1
3
  import {
2
- fetchSongById,
3
- fetchArtists,
4
- fetchSongArtistCount,
5
- fetchRelatedSongs,
6
- fetchAllSongs,
7
- fetchSongFilterOptions,
8
- fetchSongCount,
9
- fetchWorkouts,
10
- fetchNewReleases,
11
- fetchLiveEvent,
12
- fetchUpcomingEvents,
13
- fetchByRailContentId,
14
- fetchByRailContentIds,
15
- fetchAll,
16
- fetchAllFilterOptions,
17
- fetchFoundation,
18
- fetchMethods,
19
- fetchMethod,
20
- fetchMethodChildren,
21
- fetchMethodNextLesson,
22
- fetchMethodChildrenIds,
23
- fetchNextPreviousLesson,
24
- fetchRelatedLessons,
25
- fetchAllPacks,
26
- fetchPackAll,
27
- fetchPackChildren,
28
- fetchLessonContent,
29
- fetchCourseOverview,
30
- fetchChallengeOverview,
31
- fetchScheduledReleases,
32
- fetchArtistLessons,
33
- fetchGenreLessons,
34
- fetchShowsData,
35
- fetchMetadata,
36
- } from './services/sanity.js';
4
+ globalConfig,
5
+ initializeService
6
+ } from './services/config.js';
37
7
 
38
- import {
39
- fetchCompletedState,
40
- fetchAllCompletedStates,
41
- fetchContentInProgress,
42
- fetchCompletedContent,
43
- fetchVimeoData,
44
- fetchContentPageUserData,
8
+ import {
9
+ fetchAllCompletedStates,
10
+ fetchCompletedContent,
11
+ fetchCompletedState,
12
+ fetchContentInProgress,
13
+ fetchContentPageUserData,
14
+ fetchHandler,
15
+ fetchLikeContent,
16
+ fetchSongsInProgress,
17
+ fetchUnlikeContent,
18
+ fetchUserContext,
19
+ fetchVimeoData
45
20
  } from './services/railcontent.js';
46
21
 
47
- import { initializeService } from './services/config.js';
22
+ import {
23
+ fetchAll,
24
+ fetchAllFilterOptions,
25
+ fetchAllPacks,
26
+ fetchAllSongs,
27
+ fetchArtistLessons,
28
+ fetchArtists,
29
+ fetchByRailContentId,
30
+ fetchByRailContentIds,
31
+ fetchByReference,
32
+ fetchCatalogMetadata,
33
+ fetchChallengeOverview,
34
+ fetchChildren,
35
+ fetchCoachLessons,
36
+ fetchCourseOverview,
37
+ fetchFoundation,
38
+ fetchGenreLessons,
39
+ fetchLessonContent,
40
+ fetchLiveEvent,
41
+ fetchMetadata,
42
+ fetchMethod,
43
+ fetchMethodChildren,
44
+ fetchMethodChildrenIds,
45
+ fetchMethodNextLesson,
46
+ fetchMethodPreviousNextLesson,
47
+ fetchMethods,
48
+ fetchNewReleases,
49
+ fetchNextPreviousLesson,
50
+ fetchPackAll,
51
+ fetchPackChildren,
52
+ fetchParentByRailContentId,
53
+ fetchRelatedLessons,
54
+ fetchRelatedMethodLessons,
55
+ fetchRelatedSongs,
56
+ fetchSanity,
57
+ fetchScheduledReleases,
58
+ fetchShowsData,
59
+ fetchSongArtistCount,
60
+ fetchSongById,
61
+ fetchSongCount,
62
+ fetchSongFilterOptions,
63
+ fetchUpcomingEvents,
64
+ fetchWorkouts,
65
+ getSortOrder
66
+ } from './services/sanity.js';
48
67
 
68
+ import {
69
+ clearCache,
70
+ fetchContentData,
71
+ init,
72
+ likeContent,
73
+ testClearLocal,
74
+ unlikeContent,
75
+ version
76
+ } from './services/userContext.js';
49
77
 
50
78
  declare module 'musora-content-services' {
51
- export {
52
- initializeService,
53
- fetchSongById,
54
- fetchArtists,
55
- fetchSongArtistCount,
56
- fetchRelatedSongs,
57
- fetchAllSongs,
58
- fetchSongFilterOptions,
59
- fetchSongCount,
60
- fetchWorkouts,
61
- fetchNewReleases,
62
- fetchUpcomingEvents,
63
- fetchByRailContentId,
64
- fetchByRailContentIds,
65
- fetchAll,
66
- fetchAllFilterOptions,
67
- fetchFoundation,
68
- fetchMethods,
69
- fetchMethod,
70
- fetchMethodNextLesson,
71
- fetchMethodChildren,
72
- fetchMethodChildrenIds,
73
- fetchNextPreviousLesson,
74
- fetchRelatedLessons,
75
- fetchAllPacks,
76
- fetchPackAll,
77
- fetchPackChildren,
78
- fetchLessonContent,
79
- fetchCourseOverview,
80
- fetchLiveEvent,
81
- fetchChallengeOverview,
82
- fetchVimeoData,
83
- fetchCompletedState,
84
- fetchAllCompletedStates,
85
- fetchContentInProgress,
86
- fetchCompletedContent,
87
- fetchContentPageUserData,
88
- fetchScheduledReleases,
89
- fetchArtistLessons,
90
- fetchGenreLessons,
91
- fetchShowsData,
92
- fetchMetadata,
93
- }
94
-
95
- }
79
+ export {
80
+ clearCache,
81
+ fetchAll,
82
+ fetchAllCompletedStates,
83
+ fetchAllFilterOptions,
84
+ fetchAllPacks,
85
+ fetchAllSongs,
86
+ fetchArtistLessons,
87
+ fetchArtists,
88
+ fetchByRailContentId,
89
+ fetchByRailContentIds,
90
+ fetchByReference,
91
+ fetchCatalogMetadata,
92
+ fetchChallengeOverview,
93
+ fetchChildren,
94
+ fetchCoachLessons,
95
+ fetchCompletedContent,
96
+ fetchCompletedState,
97
+ fetchContentData,
98
+ fetchContentInProgress,
99
+ fetchContentPageUserData,
100
+ fetchCourseOverview,
101
+ fetchFoundation,
102
+ fetchGenreLessons,
103
+ fetchHandler,
104
+ fetchLessonContent,
105
+ fetchLikeContent,
106
+ fetchLiveEvent,
107
+ fetchMetadata,
108
+ fetchMethod,
109
+ fetchMethodChildren,
110
+ fetchMethodChildrenIds,
111
+ fetchMethodNextLesson,
112
+ fetchMethodPreviousNextLesson,
113
+ fetchMethods,
114
+ fetchNewReleases,
115
+ fetchNextPreviousLesson,
116
+ fetchPackAll,
117
+ fetchPackChildren,
118
+ fetchParentByRailContentId,
119
+ fetchRelatedLessons,
120
+ fetchRelatedMethodLessons,
121
+ fetchRelatedSongs,
122
+ fetchSanity,
123
+ fetchScheduledReleases,
124
+ fetchShowsData,
125
+ fetchSongArtistCount,
126
+ fetchSongById,
127
+ fetchSongCount,
128
+ fetchSongFilterOptions,
129
+ fetchSongsInProgress,
130
+ fetchUnlikeContent,
131
+ fetchUpcomingEvents,
132
+ fetchUserContext,
133
+ fetchVimeoData,
134
+ fetchWorkouts,
135
+ getSortOrder,
136
+ globalConfig,
137
+ init,
138
+ initializeService,
139
+ likeContent,
140
+ testClearLocal,
141
+ unlikeContent,
142
+ version,
143
+ }
144
+ }
package/src/index.js CHANGED
@@ -1,104 +1,142 @@
1
- import { initializeService } from './services/config.js';
1
+ /*** This file was generated automatically. To recreate, please run `npm run build-index`. ***/
2
2
 
3
3
  import {
4
- fetchSongById,
5
- fetchArtists,
6
- fetchSongArtistCount,
7
- fetchRelatedSongs,
8
- fetchAllSongs,
9
- fetchSongFilterOptions,
10
- fetchSongCount,
11
- fetchWorkouts,
12
- fetchNewReleases,
13
- fetchUpcomingEvents,
14
- fetchByRailContentId,
15
- fetchByRailContentIds,
16
- fetchAll,
17
- fetchAllFilterOptions,
18
- fetchMethodNextLesson,
19
- fetchFoundation,
20
- fetchMethod,
21
- fetchMethods,
22
- fetchMethodChildren,
23
- fetchMethodChildrenIds,
24
- fetchNextPreviousLesson,
25
- fetchRelatedLessons,
26
- fetchAllPacks,
27
- fetchPackAll,
28
- fetchPackChildren,
29
- fetchLessonContent,
30
- fetchCourseOverview,
31
- fetchChildren,
32
- fetchParentByRailContentId,
33
- fetchMethodPreviousNextLesson,
34
- fetchLiveEvent,
35
- fetchChallengeOverview,
36
- fetchCoachLessons,
37
- fetchByReference,
38
- fetchScheduledReleases,
39
- fetchArtistLessons,
40
- fetchGenreLessons,
41
- fetchRelatedMethodLessons,
42
- fetchShowsData,
43
- fetchMetadata,
44
- } from './services/sanity.js';
4
+ globalConfig,
5
+ initializeService
6
+ } from './services/config.js';
45
7
 
46
- import {
47
- fetchCompletedState,
48
- fetchAllCompletedStates,
49
- fetchContentInProgress,
50
- fetchCompletedContent,
51
- fetchVimeoData,
52
- fetchContentPageUserData,
8
+ import {
9
+ fetchAllCompletedStates,
10
+ fetchCompletedContent,
11
+ fetchCompletedState,
12
+ fetchContentInProgress,
13
+ fetchContentPageUserData,
14
+ fetchHandler,
15
+ fetchLikeContent,
16
+ fetchSongsInProgress,
17
+ fetchUnlikeContent,
18
+ fetchUserContext,
19
+ fetchVimeoData
53
20
  } from './services/railcontent.js';
54
21
 
22
+ import {
23
+ fetchAll,
24
+ fetchAllFilterOptions,
25
+ fetchAllPacks,
26
+ fetchAllSongs,
27
+ fetchArtistLessons,
28
+ fetchArtists,
29
+ fetchByRailContentId,
30
+ fetchByRailContentIds,
31
+ fetchByReference,
32
+ fetchCatalogMetadata,
33
+ fetchChallengeOverview,
34
+ fetchChildren,
35
+ fetchCoachLessons,
36
+ fetchCourseOverview,
37
+ fetchFoundation,
38
+ fetchGenreLessons,
39
+ fetchLessonContent,
40
+ fetchLiveEvent,
41
+ fetchMetadata,
42
+ fetchMethod,
43
+ fetchMethodChildren,
44
+ fetchMethodChildrenIds,
45
+ fetchMethodNextLesson,
46
+ fetchMethodPreviousNextLesson,
47
+ fetchMethods,
48
+ fetchNewReleases,
49
+ fetchNextPreviousLesson,
50
+ fetchPackAll,
51
+ fetchPackChildren,
52
+ fetchParentByRailContentId,
53
+ fetchRelatedLessons,
54
+ fetchRelatedMethodLessons,
55
+ fetchRelatedSongs,
56
+ fetchSanity,
57
+ fetchScheduledReleases,
58
+ fetchShowsData,
59
+ fetchSongArtistCount,
60
+ fetchSongById,
61
+ fetchSongCount,
62
+ fetchSongFilterOptions,
63
+ fetchUpcomingEvents,
64
+ fetchWorkouts,
65
+ getSortOrder
66
+ } from './services/sanity.js';
67
+
68
+ import {
69
+ clearCache,
70
+ fetchContentData,
71
+ init,
72
+ likeContent,
73
+ testClearLocal,
74
+ unlikeContent,
75
+ version
76
+ } from './services/userContext.js';
55
77
 
56
78
  export {
57
- initializeService,
58
- fetchSongById,
59
- fetchArtists,
60
- fetchSongArtistCount,
61
- fetchRelatedSongs,
62
- fetchAllSongs,
63
- fetchSongFilterOptions,
64
- fetchSongCount,
65
- fetchWorkouts,
66
- fetchNewReleases,
67
- fetchUpcomingEvents,
68
- fetchByRailContentId,
69
- fetchByRailContentIds,
70
- fetchAll,
71
- fetchAllFilterOptions,
72
- fetchFoundation,
73
- fetchMethods,
74
- fetchMethod,
75
- fetchMethodChildren,
76
- fetchMethodNextLesson,
77
- fetchMethodChildrenIds,
78
- fetchNextPreviousLesson,
79
- fetchRelatedLessons,
80
- fetchAllPacks,
81
- fetchPackAll,
82
- fetchPackChildren,
83
- fetchLessonContent,
84
- fetchCompletedState,
85
- fetchAllCompletedStates,
86
- fetchContentInProgress,
87
- fetchCompletedContent,
88
- fetchCourseOverview,
89
- fetchChildren,
90
- fetchParentByRailContentId,
91
- fetchMethodPreviousNextLesson,
92
- fetchLiveEvent,
93
- fetchChallengeOverview,
94
- fetchVimeoData,
95
- fetchContentPageUserData,
96
- fetchCoachLessons,
97
- fetchByReference,
98
- fetchScheduledReleases,
99
- fetchArtistLessons,
100
- fetchGenreLessons,
101
- fetchRelatedMethodLessons,
102
- fetchShowsData,
103
- fetchMetadata,
104
- }
79
+ clearCache,
80
+ fetchAll,
81
+ fetchAllCompletedStates,
82
+ fetchAllFilterOptions,
83
+ fetchAllPacks,
84
+ fetchAllSongs,
85
+ fetchArtistLessons,
86
+ fetchArtists,
87
+ fetchByRailContentId,
88
+ fetchByRailContentIds,
89
+ fetchByReference,
90
+ fetchCatalogMetadata,
91
+ fetchChallengeOverview,
92
+ fetchChildren,
93
+ fetchCoachLessons,
94
+ fetchCompletedContent,
95
+ fetchCompletedState,
96
+ fetchContentData,
97
+ fetchContentInProgress,
98
+ fetchContentPageUserData,
99
+ fetchCourseOverview,
100
+ fetchFoundation,
101
+ fetchGenreLessons,
102
+ fetchHandler,
103
+ fetchLessonContent,
104
+ fetchLikeContent,
105
+ fetchLiveEvent,
106
+ fetchMetadata,
107
+ fetchMethod,
108
+ fetchMethodChildren,
109
+ fetchMethodChildrenIds,
110
+ fetchMethodNextLesson,
111
+ fetchMethodPreviousNextLesson,
112
+ fetchMethods,
113
+ fetchNewReleases,
114
+ fetchNextPreviousLesson,
115
+ fetchPackAll,
116
+ fetchPackChildren,
117
+ fetchParentByRailContentId,
118
+ fetchRelatedLessons,
119
+ fetchRelatedMethodLessons,
120
+ fetchRelatedSongs,
121
+ fetchSanity,
122
+ fetchScheduledReleases,
123
+ fetchShowsData,
124
+ fetchSongArtistCount,
125
+ fetchSongById,
126
+ fetchSongCount,
127
+ fetchSongFilterOptions,
128
+ fetchSongsInProgress,
129
+ fetchUnlikeContent,
130
+ fetchUpcomingEvents,
131
+ fetchUserContext,
132
+ fetchVimeoData,
133
+ fetchWorkouts,
134
+ getSortOrder,
135
+ globalConfig,
136
+ init,
137
+ initializeService,
138
+ likeContent,
139
+ testClearLocal,
140
+ unlikeContent,
141
+ version,
142
+ };
File without changes
File without changes
@@ -217,8 +217,7 @@ export async function fetchSongFilterOptions(brand) {
217
217
  {"type": "Full Song Only", "count": count(*[_type == 'song' && brand == '${brand}' && instrumentless == false]._id)},
218
218
  {"type": "Instrument Removed", "count": count(*[_type == 'song' && brand == '${brand}' && instrumentless == true]._id)}
219
219
  ]
220
- }
221
- `;
220
+ }`;
222
221
 
223
222
  return fetchSanity(query, true);
224
223
  }
@@ -611,27 +610,22 @@ export async function fetchAllFilterOptions(
611
610
  `&& railcontent_id in [${progressIds.join(',')}]` : "";
612
611
 
613
612
  const commonFilter = `_type == '${contentType}' && brand == "${brand}"${style ? ` && '${style}' in genre[]->name` : ''}${artist ? ` && artist->name == '${artist}'` : ''} ${progressFilter} ${includedFieldsFilter ? includedFieldsFilter : ''}`;
613
+ const metaData = processMetadata(brand, contentType, true);
614
+ const allowableFilters = (metaData) ? metaData['allowableFilters'] : [];
615
+
616
+ let dynamicFilterOptions = '';
617
+ allowableFilters.forEach(filter => {
618
+ const filterOption = getFilterOptions(filter, commonFilter, contentType);
619
+ dynamicFilterOptions += filterOption;
620
+ });
621
+
614
622
  const query = `
615
623
  {
616
624
  "meta": {
617
625
  "totalResults": count(*[${commonFilter}
618
626
  ${term ? ` && (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}]),
619
627
  "filterOptions": {
620
- "difficulty": [
621
- {"type": "Introductory", "count": count(*[${commonFilter} && difficulty_string == "Introductory"])},
622
- {"type": "Beginner", "count": count(*[${commonFilter} && difficulty_string == "Beginner"])},
623
- {"type": "Intermediate", "count": count(*[${commonFilter} && difficulty_string == "Intermediate" ])},
624
- {"type": "Advanced", "count": count(*[${commonFilter} && difficulty_string == "Advanced" ])},
625
- {"type": "Expert", "count": count(*[${commonFilter} && difficulty_string == "Expert" ])}
626
- ][count > 0],
627
- "instrumentless": [
628
- {"type": "Full Song Only", "count": count(*[${commonFilter} && instrumentless == false ])},
629
- {"type": "Instrument Removed", "count": count(*[${commonFilter} && instrumentless == true ])}
630
- ][count > 0],
631
- "genre": *[_type == 'genre' && '${contentType}' in filter_types] {
632
- "type": name,
633
- "count": count(*[${commonFilter} && references(^._id)])
634
- }[count > 0]
628
+ ${dynamicFilterOptions}
635
629
  }
636
630
  }
637
631
  }`;
@@ -830,8 +824,6 @@ function getChildrenToDepth(parent, depth = 1)
830
824
  return allChildrenIds;
831
825
  }
832
826
 
833
-
834
-
835
827
  /**
836
828
  * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
837
829
  * @param {string} railcontentId - The Railcontent ID of the current lesson.
@@ -974,13 +966,15 @@ export async function fetchAllPacks(brand, sort = "-published_on", searchTerm =
974
966
  const sortOrder = getSortOrder(sort);
975
967
  const filter = `_type == 'pack' && brand == '${brand}' && title match "${searchTerm}*"`
976
968
  const filterParams = {};
969
+ const fields = getFieldsForContentType('pack');
977
970
  const query = buildQuery(
978
971
  filter,
979
972
  filterParams,
980
- getFieldsForContentType('pack'),
981
- {
982
- sortOrder: sortOrder,
983
- }
973
+ fields,
974
+ {
975
+ logo_image_url: 'logo_image_url.asset->url',
976
+ sortOrder: sortOrder,
977
+ }
984
978
  );
985
979
  return fetchSanity(query, true);
986
980
  }
@@ -1488,6 +1482,64 @@ function processMetadata(brand, type, withFilters = false) {
1488
1482
  return processedData;
1489
1483
  }
1490
1484
 
1485
+ function getFilterOptions(option, commonFilter,contentType){
1486
+ let filterGroq = '';
1487
+ switch (option) {
1488
+ case "difficulty":
1489
+ filterGroq = `
1490
+ "difficulty": [
1491
+ {"type": "Introductory", "count": count(*[${commonFilter} && difficulty_string == "Introductory"])},
1492
+ {"type": "Beginner", "count": count(*[${commonFilter} && difficulty_string == "Beginner"])},
1493
+ {"type": "Intermediate", "count": count(*[${commonFilter} && difficulty_string == "Intermediate" ])},
1494
+ {"type": "Advanced", "count": count(*[${commonFilter} && difficulty_string == "Advanced" ])},
1495
+ {"type": "Expert", "count": count(*[${commonFilter} && difficulty_string == "Expert" ])}
1496
+ ][count > 0],`;
1497
+ break;
1498
+ case "genre":
1499
+ case "essential":
1500
+ case "focus":
1501
+ case "theory":
1502
+ case "topic":
1503
+ case "lifestyle":
1504
+ case "creativity":
1505
+ filterGroq = `
1506
+ "${option}": *[_type == '${option}' && '${contentType}' in filter_types] {
1507
+ "type": name,
1508
+ "count": count(*[${commonFilter} && references(^._id)])
1509
+ }[count > 0],`;
1510
+ break;
1511
+ case "instrumentless":
1512
+ filterGroq = `
1513
+ "${option}": [
1514
+ {"type": "Full Song Only", "count": count(*[${commonFilter} && instrumentless == false ])},
1515
+ {"type": "Instrument Removed", "count": count(*[${commonFilter} && instrumentless == true ])}
1516
+ ][count > 0],`;
1517
+ break;
1518
+ case "gear":
1519
+ filterGroq = `
1520
+ "${option}": [
1521
+ {"type": "Practice Pad", "count": count(*[${commonFilter} && gear match 'Practice Pad' ])},
1522
+ {"type": "Drum-Set", "count": count(*[${commonFilter} && gear match 'Drum-Set'])}
1523
+ ][count > 0],`;
1524
+ break;
1525
+ case "bpm":
1526
+ filterGroq = `
1527
+ "${option}": [
1528
+ {"type": "50-90", "count": count(*[${commonFilter} && bpm > 50 && bpm < 91])},
1529
+ {"type": "91-120", "count": count(*[${commonFilter} && bpm > 90 && bpm < 121])},
1530
+ {"type": "121-150", "count": count(*[${commonFilter} && bpm > 120 && bpm < 151])},
1531
+ {"type": "151-180", "count": count(*[${commonFilter} && bpm > 150 && bpm < 181])},
1532
+ {"type": "180+", "count": count(*[${commonFilter} && bpm > 180])},
1533
+ ][count > 0],`;
1534
+ break;
1535
+ default:
1536
+ filterGroq = "";
1537
+ break;
1538
+ }
1539
+
1540
+ return filterGroq;
1541
+ }
1542
+
1491
1543
 
1492
1544
 
1493
1545
 
File without changes
File without changes
package/test/log.js CHANGED
File without changes
@@ -517,4 +517,36 @@ describe('Filter Builder', function () {
517
517
  return clauses;
518
518
  }
519
519
 
520
+ test('fetchAllFilterOptions', async () => {
521
+ let response = await fetchAllFilterOptions('drumeo', '', '', '', 'song', '');
522
+ log(response);
523
+ expect(response.meta.filterOptions.difficulty).toBeDefined();
524
+ expect(response.meta.filterOptions.genre).toBeDefined();
525
+ expect(response.meta.filterOptions.lifestyle).toBeDefined();
526
+ expect(response.meta.filterOptions.instrumentless).toBeDefined();
527
+ });
528
+
529
+ test('fetchAllFilterOptions-Rudiment', async () => {
530
+ let response = await fetchAllFilterOptions('drumeo', '', '', '', 'rudiment', '');
531
+ log(response);
532
+ expect(response.meta.filterOptions.gear).toBeDefined();
533
+ expect(response.meta.filterOptions.genre).toBeDefined();
534
+ expect(response.meta.filterOptions.topic).toBeDefined();
535
+ });
536
+ test('fetchAllFilterOptions-PlayAlong', async () => {
537
+ let response = await fetchAllFilterOptions('drumeo', '', '', '', 'play-along', '');
538
+ log(response);
539
+ expect(response.meta.filterOptions.difficulty).toBeDefined();
540
+ expect(response.meta.filterOptions.genre).toBeDefined();
541
+ expect(response.meta.filterOptions.bpm).toBeDefined();
542
+ });
543
+
544
+ test('fetchAllFilterOptions-Coaches', async () => {
545
+ let response = await fetchAllFilterOptions('drumeo', '', '', '', 'instructor', '');
546
+ log(response);
547
+ expect(response.meta.filterOptions.focus).toBeDefined();
548
+ expect(response.meta.filterOptions.focus.length).toBeGreaterThan(0);
549
+ expect(response.meta.filterOptions.genre).toBeDefined();
550
+ expect(response.meta.filterOptions.genre.length).toBeGreaterThan(0);
551
+ });
520
552
  });
File without changes
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tool script to generate index.js and index.d.ts files based on exports from files in our services directory.
3
+ * This scans all files from the src/services directory and retrieves any functions that are declared with
4
+ * `export function` or `export async function`. It also retrieves ES module exports through `module.exports`. *
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const fileExports = {};
10
+
11
+ /**
12
+ * Helper function to extract function names from ES module and CommonJS exports
13
+ *
14
+ * @param filePath
15
+ * @returns {string[]}
16
+ */
17
+ function extractExportedFunctions(filePath) {
18
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
19
+
20
+ const exportRegex = /export\s+(async\s+)?function\s+(\w+)/g;
21
+ const moduleExportsRegex = /module\.exports\s*=\s*{\s*([\s\S]+?)\s*};/g;
22
+
23
+ let matches = [...fileContent.matchAll(exportRegex)].map(match => match[2]);
24
+
25
+ const moduleExportsMatch = moduleExportsRegex.exec(fileContent);
26
+ if (moduleExportsMatch) {
27
+ const exportsList = moduleExportsMatch[1]
28
+ .split(',')
29
+ .map(exp => exp.split(':')[0].trim());
30
+ matches = matches.concat(exportsList);
31
+ }
32
+
33
+ return matches.sort();
34
+ }
35
+
36
+
37
+ // get all files in the services directory
38
+ const servicesDir = path.join(__dirname, '../src/services');
39
+ const files = fs.readdirSync(servicesDir);
40
+
41
+ files.forEach((file) => {
42
+ const filePath = path.join(servicesDir, file);
43
+ const functionNames = extractExportedFunctions(filePath);
44
+
45
+ if (functionNames.length > 0) {
46
+ fileExports[file] = functionNames;
47
+ }
48
+ });
49
+
50
+ // populate the index.js content string with the import/export of all functions
51
+ let content = '/*** This file was generated automatically. To recreate, please run `npm run build-index`. ***/\n';
52
+
53
+ Object.entries(fileExports).forEach(([file, functionNames]) => {
54
+ content += `\nimport {\n\t${functionNames.join(',\n\t')}\n} from './services/${file}';\n`;
55
+ });
56
+
57
+ const allFunctionNames = Object.values(fileExports).flat().sort();
58
+ content += '\nexport {\n';
59
+ content += `\t${allFunctionNames.join(',\n\t')},\n`;
60
+ content += '};\n';
61
+
62
+ // write the generated content to index.js
63
+ const outputPath = path.join(__dirname, '../src/index.js');
64
+ fs.writeFileSync(outputPath, content);
65
+
66
+ console.log('index.js generated successfully!');
67
+
68
+ // populate the index.d.ts content string with the import and module export of all functions
69
+ let dtsContent = '/*** This file was generated automatically. To recreate, please run `npm run build-index`. ***/\n';
70
+
71
+ Object.entries(fileExports).forEach(([file, functionNames]) => {
72
+ dtsContent += `\nimport {\n\t${functionNames.join(',\n\t')}\n} from './services/${file}';\n`;
73
+ });
74
+
75
+ dtsContent += '\ndeclare module \'musora-content-services\' {\n';
76
+ dtsContent += '\texport {\n';
77
+ dtsContent += `\t\t${allFunctionNames.join(',\n\t\t')},\n`;
78
+ dtsContent += '\t}\n';
79
+ dtsContent += '}\n';
80
+
81
+ // write the generated content to index.d.ts
82
+ const outputDtsPath = path.join(__dirname, '../src/index.d.ts');
83
+ fs.writeFileSync(outputDtsPath, dtsContent);
84
+
85
+ console.log('index.d.ts generated successfully!');