musora-content-services 1.0.7 → 1.0.9

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.
@@ -24,7 +24,7 @@
24
24
  <label for="nav-trigger" class="overlay"></label>
25
25
 
26
26
  <nav>
27
- <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchAll">fetchAll</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchAllSongs">fetchAllSongs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchArtists">fetchArtists</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchByRailContentId">fetchByRailContentId</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchByRailContentIds">fetchByRailContentIds</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchChildren">fetchChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchFilterOptions">fetchFilterOptions</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchMethodChildren">fetchMethodChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchMethodNextLesson">fetchMethodNextLesson</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchNewReleases">fetchNewReleases</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchNextPreviousLesson">fetchNextPreviousLesson</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchPackAll">fetchPackAll</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchPackChildren">fetchPackChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchRelatedLessons">fetchRelatedLessons</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchRelatedSongs">fetchRelatedSongs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSanity">fetchSanity</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongById">fetchSongById</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongCount">fetchSongCount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchUpcomingEvents">fetchUpcomingEvents</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchWorkouts">fetchWorkouts</a></span></li>
27
+ <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchAll">fetchAll</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchAllFilterOptions">fetchAllFilterOptions</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchAllSongs">fetchAllSongs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchArtists">fetchArtists</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchByRailContentId">fetchByRailContentId</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchByRailContentIds">fetchByRailContentIds</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchChildren">fetchChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchLessonContent">fetchLessonContent</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchMethodChildren">fetchMethodChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchMethodNextLesson">fetchMethodNextLesson</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchNewReleases">fetchNewReleases</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchNextPreviousLesson">fetchNextPreviousLesson</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchPackAll">fetchPackAll</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchPackChildren">fetchPackChildren</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchRelatedLessons">fetchRelatedLessons</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchRelatedSongs">fetchRelatedSongs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSanity">fetchSanity</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongArtistCount">fetchSongArtistCount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongById">fetchSongById</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongCount">fetchSongCount</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchSongFilterOptions">fetchSongFilterOptions</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchUpcomingEvents">fetchUpcomingEvents</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#fetchWorkouts">fetchWorkouts</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#initializeSanityService">initializeSanityService</a></span></li>
28
28
  </nav>
29
29
 
30
30
  <div id="main">
@@ -39,15 +39,40 @@
39
39
 
40
40
  <section>
41
41
  <article>
42
- <pre class="prettyprint source linenums"><code>
42
+ <pre class="prettyprint source linenums"><code>let globalConfig = {};
43
+
44
+ /**
45
+ * Initializes the Sanity service with the given configuration.
46
+ * This function must be called before using any other functions in this library.
47
+ *
48
+ * @param {Object} config - Configuration object containing Sanity API settings.
49
+ * @param {string} config.token - The API token for authenticating with Sanity.
50
+ * @param {string} config.projectId - The project ID in Sanity.
51
+ * @param {string} config.dataset - The dataset name in Sanity.
52
+ * @param {string} config.version - The API version to use.
53
+ * @param {boolean} [config.debug=false] - Optional flag to enable debug mode, which logs the query and results.
54
+ * @param {boolean} [config.useCachedAPI=true] - Optional flag to disable cached API. *
55
+ * @example
56
+ * // Initialize the Sanity service in your app.js
57
+ * initializeSanityService({
58
+ * token: 'your-sanity-api-token',
59
+ * projectId: 'your-sanity-project-id',
60
+ * dataset: 'your-dataset-name',
61
+ * version: '2021-06-07',
62
+ * debug: true // Optional: Enable debug mode
63
+ * useCachedAPI: true // Optional: Use cached API
64
+ * });
65
+ */
66
+ function initializeSanityService(config) {
67
+ globalConfig = config;
68
+ }
43
69
 
44
70
  /**
45
71
  * Fetch a song by its document ID from Sanity.
46
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
47
72
  * @param {string} documentId - The ID of the document to fetch.
48
73
  * @returns {Promise&lt;Object|null>} - The fetched song data or null if not found.
49
74
  */
50
- export async function fetchSongById(config, documentId) {
75
+ async function fetchSongById(documentId) {
51
76
  const fields = [
52
77
  'title',
53
78
  '"thumbnail_url": thumbnail.asset->url',
@@ -56,6 +81,7 @@ export async function fetchSongById(config, documentId) {
56
81
  'album',
57
82
  'instrumentless',
58
83
  'soundslice',
84
+ 'railcontent_id',
59
85
  '"resources": resource[]{resource_url, resource_name}',
60
86
  ];
61
87
 
@@ -63,32 +89,40 @@ export async function fetchSongById(config, documentId) {
63
89
  *[_type == "song" &amp;&amp; railcontent_id == ${documentId}]{
64
90
  ${fields.join(', ')}
65
91
  }`;
66
- return fetchSanity(config, query);
92
+ return fetchSanity(query, false);
67
93
  }
68
94
 
69
95
  /**
70
96
  * Fetch all artists with lessons available for a specific brand.
71
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
72
97
  * @param {string} brand - The brand for which to fetch artists.
73
98
  * @returns {Promise&lt;Object|null>} - The fetched artist data or null if not found.
74
99
  */
75
- export async function fetchArtists(config, brand) {
100
+ async function fetchArtists(brand) {
76
101
  const query = `
77
102
  *[_type == "artist"]{
78
103
  name,
79
104
  "lessonsCount": count(*[_type == "song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^._id)])
80
105
  }[lessonsCount > 0]`;
81
- return fetchSanity(config, query, true);
106
+ return fetchSanity(query, true);
107
+ }
108
+
109
+ /**
110
+ * Fetch current number of artists for songs within a brand.
111
+ * @param {string} brand - The current brand.
112
+ * @returns {Promise&lt;int|null>} - The fetched count of artists.
113
+ */
114
+ async function fetchSongArtistCount(brand) {
115
+ const query = `count(*[_type == 'artist']{'lessonsCount': count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; references(^._id)]._id)}[lessonsCount > 0])`;
116
+ return fetchSanity(query, false);
82
117
  }
83
118
 
84
119
  /**
85
120
  * Fetch related songs for a specific brand and song ID.
86
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
87
121
  * @param {string} brand - The brand for which to fetch related songs.
88
122
  * @param {string} songId - The ID of the song to find related songs for.
89
123
  * @returns {Promise&lt;Object|null>} - The fetched related songs data or null if not found.
90
124
  */
91
- export async function fetchRelatedSongs(config, brand, songId) {
125
+ async function fetchRelatedSongs(brand, songId) {
92
126
  const query = `
93
127
  *[_type == "song" &amp;&amp; railcontent_id == ${songId}]{
94
128
  "data": array::unique([
@@ -153,12 +187,11 @@ export async function fetchRelatedSongs(config, brand, songId) {
153
187
  ])[0...10]
154
188
  }`;
155
189
 
156
- return fetchSanity(config, query);
190
+ return fetchSanity(query, true);
157
191
  }
158
192
 
159
193
  /**
160
194
  * Fetch all songs for a specific brand with pagination and search options.
161
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
162
195
  * @param {string} brand - The brand for which to fetch songs.
163
196
  * @param {Object} params - Parameters for pagination, filtering, and sorting.
164
197
  * @param {number} [params.page=1] - The page number for pagination.
@@ -169,7 +202,14 @@ export async function fetchRelatedSongs(config, brand, songId) {
169
202
  * @param {string} [params.groupBy=""] - The field to group the results by.
170
203
  * @returns {Promise&lt;Object|null>} - The fetched song data or null if not found.
171
204
  */
172
- export async function fetchAllSongs(config, brand, { page = 1, limit = 10, searchTerm = "", sort = "-published_on", includedFields = [] , groupBy = "" }) {
205
+ async function fetchAllSongs(brand, {
206
+ page = 1,
207
+ limit = 10,
208
+ searchTerm = "",
209
+ sort = "-published_on",
210
+ includedFields = [],
211
+ groupBy = ""
212
+ }) {
173
213
  console.log('groupBy', groupBy)
174
214
  const start = (page - 1) * limit;
175
215
  const end = start + limit;
@@ -287,16 +327,15 @@ export async function fetchAllSongs(config, brand, { page = 1, limit = 10, searc
287
327
  `;
288
328
  }
289
329
 
290
- return fetchSanity(config, query);
330
+ return fetchSanity(query, false);
291
331
  }
292
332
 
293
333
  /**
294
334
  * Fetch filter options for a specific brand.
295
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
296
335
  * @param {string} brand - The brand for which to fetch filter options.
297
336
  * @returns {Promise&lt;Object|null>} - The fetched filter options or null if not found.
298
337
  */
299
- export async function fetchFilterOptions(config, brand) {
338
+ async function fetchSongFilterOptions(brand) {
300
339
  const query = `
301
340
  {
302
341
  "difficulty": [
@@ -317,27 +356,25 @@ export async function fetchFilterOptions(config, brand) {
317
356
  }
318
357
  `;
319
358
 
320
- return fetchSanity(config, query);
359
+ return fetchSanity(query, false);
321
360
  }
322
361
 
323
362
  /**
324
363
  * Fetch the total count of songs for a specific brand.
325
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
326
364
  * @param {string} brand - The brand for which to fetch the song count.
327
365
  * @returns {Promise&lt;number|null>} - The total count of songs or null if an error occurs.
328
366
  */
329
- export async function fetchSongCount(config, brand) {
367
+ async function fetchSongCount(brand) {
330
368
  const query = `count(*[_type == 'song' &amp;&amp; brand == "${brand}"])`;
331
- return fetchSanity(config, query);
369
+ return fetchSanity(query, false);
332
370
  }
333
371
 
334
372
  /**
335
373
  * Fetch the latest workouts for the home page of a specific brand.
336
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
337
374
  * @param {string} brand - The brand for which to fetch workouts.
338
375
  * @returns {Promise&lt;Object|null>} - The fetched workout data or null if not found.
339
376
  */
340
- export async function fetchWorkouts(config, brand) {
377
+ async function fetchWorkouts(brand) {
341
378
  const query = `*[_type == 'workout' &amp;&amp; brand == '${brand}'] [0...5] {
342
379
  railcontent_id,
343
380
  title,
@@ -349,16 +386,15 @@ export async function fetchWorkouts(config, brand) {
349
386
  web_url_path,
350
387
  published_on
351
388
  } | order(published_on desc)[0...5]`
352
- return fetchSanity(config, query);
389
+ return fetchSanity(query, true);
353
390
  }
354
391
 
355
392
  /**
356
393
  * Fetch the latest new releases for a specific brand.
357
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
358
394
  * @param {string} brand - The brand for which to fetch new releases.
359
395
  * @returns {Promise&lt;Object|null>} - The fetched new releases data or null if not found.
360
396
  */
361
- export async function fetchNewReleases(config, brand) {
397
+ async function fetchNewReleases(brand) {
362
398
  const newTypes = {
363
399
  'drumeo': ["drum-fest-international-2022", "spotlight", "the-history-of-electronic-drums", "backstage-secrets", "quick-tips", "question-and-answer", "student-collaborations", "live-streams", "live", "podcasts", "solos", "boot-camps", "gear-guides", "performances", "in-rhythm", "challenges", "on-the-road", "diy-drum-experiments", "rhythmic-adventures-of-captain-carson", "study-the-greats", "rhythms-from-another-planet", "tama-drums", "paiste-cymbals", "behind-the-scenes", "exploring-beats", "sonor-drums", "course", "play-along", "student-focus", "coach-stream", "learning-path-level", "unit", "quick-tips", "live", "question-and-answer", "student-review", "boot-camps", "song", "chords-and-scales", "pack", "podcasts", "workout", "challenge", "challenge-part"],
364
400
  'pianote': ["student-review", "student-reviews", "question-and-answer", "course", "play-along", "student-focus", "coach-stream", "learning-path-level", "unit", "quick-tips", "live", "question-and-answer", "student-review", "boot-camps", "song", "chords-and-scales", "pack", "podcasts", "workout", "challenge", "challenge-part"],
@@ -378,16 +414,15 @@ export async function fetchNewReleases(config, brand) {
378
414
  web_url_path,
379
415
  published_on
380
416
  } | order(published_on desc)[0...5]`
381
- return fetchSanity(config, query);
417
+ return fetchSanity(query, true);
382
418
  }
383
419
 
384
420
  /**
385
421
  * Fetch upcoming events for a specific brand.
386
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
387
422
  * @param {string} brand - The brand for which to fetch upcoming events.
388
423
  * @returns {Promise&lt;Object|null>} - The fetched upcoming events data or null if not found.
389
424
  */
390
- export async function fetchUpcomingEvents(config, brand) {
425
+ async function fetchUpcomingEvents(brand) {
391
426
  const liveTypes = {
392
427
  'drumeo': ["drum-fest-international-2022", "spotlight", "the-history-of-electronic-drums", "backstage-secrets", "quick-tips", "question-and-answer", "student-collaborations", "live-streams", "live", "podcasts", "solos", "boot-camps", "gear-guides", "performances", "in-rhythm", "challenges", "on-the-road", "diy-drum-experiments", "rhythmic-adventures-of-captain-carson", "study-the-greats", "rhythms-from-another-planet", "tama-drums", "paiste-cymbals", "behind-the-scenes", "exploring-beats", "sonor-drums", "student-focus", "coach-stream", "live", "question-and-answer", "student-review", "boot-camps", "recording", "pack-bundle-lesson"],
393
428
  'pianote': ["student-review", "student-reviews", "question-and-answer", "student-focus", "coach-stream", "live", "question-and-answer", "student-review", "boot-camps", "recording", "pack-bundle-lesson"],
@@ -409,17 +444,16 @@ export async function fetchUpcomingEvents(config, brand) {
409
444
  web_url_path,
410
445
  published_on
411
446
  } | order(published_on asc)[0...5]`;
412
- return fetchSanity(config, query);
447
+ return fetchSanity(query, true);
413
448
  }
414
449
 
415
450
  /**
416
451
  * Fetch content by a specific Railcontent ID.
417
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
418
452
  * @param {string} id - The Railcontent ID of the content to fetch.
419
453
  * @returns {Promise&lt;Object|null>} - The fetched content data or null if not found.
420
454
  */
421
- export async function fetchByRailContentId(config, id) {
422
- const query = `*[railcontent_id = ${id}]{
455
+ async function fetchByRailContentId(id) {
456
+ const query = `*[railcontent_id == ${id}]{
423
457
  railcontent_id,
424
458
  title,
425
459
  "image": thumbnail.asset->url,
@@ -430,16 +464,15 @@ export async function fetchByRailContentId(config, id) {
430
464
  web_url_path,
431
465
  published_on
432
466
  }`
433
- return fetchSanity(config, query);
467
+ return fetchSanity(query, false);
434
468
  }
435
469
 
436
470
  /**
437
471
  * Fetch content by an array of Railcontent IDs.
438
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
439
472
  * @param {Array&lt;string>} ids - The array of Railcontent IDs of the content to fetch.
440
473
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched content data or null if not found.
441
474
  */
442
- export async function fetchByRailContentIds(config, ids) {
475
+ async function fetchByRailContentIds(ids) {
443
476
  const idsString = ids.join(',');
444
477
  const query = `*[railcontent_id in [${idsString}]]{
445
478
  railcontent_id,
@@ -452,12 +485,11 @@ export async function fetchByRailContentIds(config, ids) {
452
485
  web_url_path,
453
486
  published_on
454
487
  }`
455
- return fetchSanity(config, query);
488
+ return fetchSanity(query, true);
456
489
  }
457
490
 
458
491
  /**
459
492
  * Fetch all content for a specific brand and type with pagination, search, and grouping options.
460
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
461
493
  * @param {string} brand - The brand for which to fetch content.
462
494
  * @param {string} type - The content type to fetch (e.g., 'song', 'artist').
463
495
  * @param {Object} params - Parameters for pagination, filtering, sorting, and grouping.
@@ -469,7 +501,14 @@ export async function fetchByRailContentIds(config, ids) {
469
501
  * @param {string} [params.groupBy=""] - The field to group the results by (e.g., 'artist', 'genre').
470
502
  * @returns {Promise&lt;Object|null>} - The fetched content data or null if not found.
471
503
  */
472
- export async function fetchAll(config, brand, type, { page = 1, limit = 10, searchTerm = "", sort = "-published_on", includedFields = [], groupBy = "" }) {
504
+ async function fetchAll(brand, type, {
505
+ page = 1,
506
+ limit = 10,
507
+ searchTerm = "",
508
+ sort = "-published_on",
509
+ includedFields = [],
510
+ groupBy = ""
511
+ }) {
473
512
  const start = (page - 1) * limit;
474
513
  const end = start + limit;
475
514
 
@@ -514,7 +553,8 @@ export async function fetchAll(config, brand, type, { page = 1, limit = 10, sear
514
553
 
515
554
  // Determine the group by clause
516
555
  let query = "";
517
- if (groupBy !== "") {
556
+ let manyReference = true; //TODO: define whether reference is one to one or one to many
557
+ if (groupBy !== "" &amp;&amp; !manyReference) {
518
558
  query = `
519
559
  {
520
560
  "total": count(*[_type == '${groupBy}' &amp;&amp; count(*[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ]._id) > 0]),
@@ -539,6 +579,31 @@ export async function fetchAll(config, brand, type, { page = 1, limit = 10, sear
539
579
  |order(${sortOrder})
540
580
  [${start}...${end}]
541
581
  }`;
582
+ } else if (groupBy !== "" &amp;&amp; manyReference) {
583
+ query = `
584
+ {
585
+ "total": count(*[_type == '${groupBy}' &amp;&amp; count(*[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref]._id)>0]),
586
+ "entity": *[_type == '${groupBy}' &amp;&amp; count(*[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref]._id) > 0]
587
+ {
588
+ 'id': _id,
589
+ 'type': _type,
590
+ name,
591
+ 'head_shot_picture_url': thumbnail_url.asset->url,
592
+ 'all_lessons_count': count(*[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ]._id),
593
+ 'lessons': *[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ]{
594
+ railcontent_id,
595
+ title,
596
+ "image": thumbnail.asset->url,
597
+ difficulty,
598
+ difficulty_string,
599
+ web_url_path,
600
+ published_on,
601
+ ${groupBy}
602
+ }[0...10]
603
+ }
604
+ |order(${sortOrder})
605
+ [${start}...${end}]
606
+ }`;
542
607
  } else {
543
608
  query = `
544
609
  {
@@ -556,16 +621,73 @@ export async function fetchAll(config, brand, type, { page = 1, limit = 10, sear
556
621
  `;
557
622
  }
558
623
 
559
- return fetchSanity(config, query);
624
+ return fetchSanity(query, false);
625
+ }
626
+
627
+ /**
628
+ * Fetches all available filter options based on various criteria such as brand, filters, style, artist, content type, and search term.
629
+ *
630
+ * This function constructs a query to retrieve the total number of results and filter options such as difficulty, instrument type, and genre.
631
+ * The filter options are dynamically generated based on the provided filters, style, artist, and content type.
632
+ *
633
+ * @param {string} brand - The brand for which to fetch the filter options.
634
+ * @param {string} filters - Additional filters to apply to the query, typically in the format of Sanity GROQ queries.
635
+ * @param {string} [style] - Optional style or genre to filter the results. If provided, the query will check if the style exists in the genre array.
636
+ * @param {string} [artist] - Optional artist name to filter the results. If provided, the query will check if the artist's name matches.
637
+ * @param {string} contentType - The content type to fetch (e.g., 'song', 'lesson').
638
+ * @param {string} [term] - Optional search term to match against various fields such as title, album, artist name, and genre.
639
+ *
640
+ * @returns {Promise&lt;Object|null>} - A promise that resolves to an object containing the total results and filter options, or null if the query fails.
641
+ *
642
+ * @example
643
+ * // Example usage:
644
+ * fetchAllFilterOptions('myBrand', '', 'Rock', 'John Doe', 'song', 'Love')
645
+ * .then(options => console.log(options))
646
+ * .catch(error => console.error(error));
647
+ */
648
+ async function fetchAllFilterOptions(
649
+ brand,
650
+ filters,
651
+ style,
652
+ artist,
653
+ contentType,
654
+ term
655
+ ){
656
+ const query = `
657
+ {
658
+ "meta": {
659
+ "totalResults": count(*[_type == '${contentType}' &amp;&amp; brand == "${brand}" &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} ${filters}
660
+ ${term ? `&amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}]),
661
+ "filterOptions": {
662
+ "difficulty": [
663
+ {"type": "Introductory", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; difficulty_string == "Introductory" ${filters}])},
664
+ {"type": "Beginner", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; difficulty_string == "Beginner" ${filters}])},
665
+ {"type": "Intermediate", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; difficulty_string == "Intermediate" ${filters}])},
666
+ {"type": "Advanced", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; difficulty_string == "Advanced" ${filters}])},
667
+ {"type": "Expert", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; difficulty_string == "Expert" ${filters}])}
668
+ ][count > 0],
669
+ "instrumentless": [
670
+ {"type": "Full Song Only", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; instrumentless == false ${filters}])},
671
+ {"type": "Instrument Removed", "count": count(*[_type == '${contentType}' &amp;&amp; brand == '${brand}' &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; instrumentless == true ${filters}])}
672
+ ][count > 0],
673
+ "genre": *[_type == 'genre' &amp;&amp; '${contentType}' in filter_types] {
674
+ "type": name,
675
+ "count": count(*[_type == '${contentType}' &amp;&amp; brand == "${brand}" &amp;&amp; ${style ? `'${style}' in genre[]->name` : `artist->name == '${artist}'`} &amp;&amp; references(^._id)])
676
+ }[count > 0]
677
+ }
678
+ }
679
+ }
680
+ `;
681
+
682
+ return fetchSanity(query, false);
560
683
  }
561
684
 
562
685
  /**
563
686
  * Fetch children content by Railcontent ID.
564
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
565
687
  * @param {string} railcontentId - The Railcontent ID of the parent content.
566
688
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children content data or null if not found.
567
689
  */
568
- export async function fetchChildren(config, railcontentId) {
690
+ async function fetchChildren(railcontentId) {
569
691
  //TODO: Implement getByParentId include sum XP
570
692
  const query = `*[_railcontent_id == ${railcontentId}]{
571
693
  railcontent_id,
@@ -578,16 +700,15 @@ export async function fetchChildren(config, railcontentId) {
578
700
  web_url_path,
579
701
  published_on
580
702
  } | order(published_on asc)`
581
- return fetchSanity(config, query);
703
+ return fetchSanity(query, true);
582
704
  }
583
705
 
584
706
  /**
585
707
  * Fetch the next lesson for a specific method by Railcontent ID.
586
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
587
708
  * @param {string} railcontentId - The Railcontent ID of the current lesson.
588
709
  * @returns {Promise&lt;Object|null>} - The fetched next lesson data or null if not found.
589
710
  */
590
- export async function fetchMethodNextLesson(config, railcontentId) {
711
+ async function fetchMethodNextLesson(railcontentId) {
591
712
  //TODO: Implement getNextContentForParentContentForUser
592
713
  const query = `*[_railcontent_id == ${railcontentId}]{
593
714
  railcontent_id,
@@ -600,27 +721,25 @@ export async function fetchMethodNextLesson(config, railcontentId) {
600
721
  web_url_path,
601
722
  published_on
602
723
  }`
603
- return fetchSanity(config, query);
724
+ return fetchSanity(query, false);
604
725
  }
605
726
 
606
727
  /**
607
728
  * Fetch all children of a specific method by Railcontent ID.
608
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
609
729
  * @param {string} railcontentId - The Railcontent ID of the method.
610
730
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched children data or null if not found.
611
731
  */
612
- export async function fetchMethodChildren(config, railcontentId) {
732
+ async function fetchMethodChildren(railcontentId) {
613
733
  //TODO: Implement getByParentId include sum XP
614
734
  return fetchChildren(railcontentId);
615
735
  }
616
736
 
617
737
  /**
618
738
  * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
619
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
620
739
  * @param {string} railcontentId - The Railcontent ID of the current lesson.
621
740
  * @returns {Promise&lt;Object|null>} - The fetched next and previous lesson data or null if found.
622
741
  */
623
- export async function fetchNextPreviousLesson(config, railcontentId) {
742
+ async function fetchNextPreviousLesson(railcontentId) {
624
743
  //TODO: Implement getTypeNeighbouringSiblings/getNextAndPreviousLessons
625
744
  const query = `*[_railcontent_id == ${railcontentId}]{
626
745
  railcontent_id,
@@ -633,45 +752,69 @@ export async function fetchNextPreviousLesson(config, railcontentId) {
633
752
  web_url_path,
634
753
  published_on
635
754
  }`
636
- return fetchSanity(config, query);
755
+ return fetchSanity(query, false);
637
756
  }
638
757
 
639
758
  /**
640
- * Fetch related lessons for a specific lesson by Railcontent ID and type.
641
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
642
- * @param {string} railcontentId - The Railcontent ID of the current lesson.
643
- * @param {string} type - The type of related lessons to fetch.
759
+ * Fetch the page data for a specific lesson by Railcontent ID.
760
+ * @param {string} railContentId - The Railcontent ID of the current lesson.
761
+ * @returns {Promise&lt;Object|null>} - The fetched page data or null if found.
762
+ */
763
+ async function fetchLessonContent(railContentId) {
764
+ const query = `*[railcontent_id == ${railContentId} ]
765
+ {title, published_on,"type":_type, "resources": resource, difficulty, difficulty_string, brand, soundslice, instrumentless, railcontent_id, "id":railcontent_id, slug, artist->,"thumbnail_url":thumbnail.asset->url, "url": web_url_path, soundslice_slug,description,
766
+ "chapters": chapter[]{
767
+ chapter_description,
768
+ chapter_timecode,
769
+ "chapter_thumbnail_url": chapter_thumbnail_url.asset->url
770
+ },
771
+ "coaches": instructor[]-> {
772
+ name,
773
+ "id":_id,
774
+ "coach_profile_image":thumbnail_url.asset->url
775
+ },
776
+ "instructors":instructor[]->name,
777
+ instructor[]->,
778
+ "assignments":assignment[]{
779
+ "id": railcontent_id,
780
+ "soundslice_slug": assignment_soundslice,
781
+ "title": assignment_title,
782
+ "sheet_music_image_url": assignment_sheet_music_image,
783
+ "timecode": assignment_timecode,
784
+ "description": assignment_description
785
+ },
786
+ video}`
787
+ return fetchSanity(query, false);
788
+ }
789
+
790
+ /**
791
+ * Fetch related lessons for a specific lesson by RailContent ID and type.
792
+ * @param {string} railContentId - The RailContent ID of the current lesson.
793
+ * @param {string} brand - The current brand.
644
794
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched related lessons data or null if not found.
645
795
  */
646
- export async function fetchRelatedLessons(config, railcontentId, type) {
647
- let sort = 'published_on'
648
- if (type == 'rhythmic-adventures-of-captain-carson' ||
649
- type == 'diy-drum-experiments' ||
650
- type == 'in-rhythm') {
651
- sort = 'sort';
652
- }
796
+ async function fetchRelatedLessons(railContentId, brand) {
797
+ // let sort = 'published_on'
798
+ // if (type == 'rhythmic-adventures-of-captain-carson' ||
799
+ // type == 'diy-drum-experiments' ||
800
+ // type == 'in-rhythm') {
801
+ // sort = 'sort';
802
+ // }
653
803
  //TODO: Implement $this->contentService->getFiltered
654
- const query = `*[_railcontent_id == ${railcontentId}]{
655
- railcontent_id,
656
- title,
657
- "image": thumbnail.asset->url,
658
- "artist_name": artist->name,
659
- artist,
660
- difficulty,
661
- difficulty_string,
662
- web_url_path,
663
- published_on
664
- } | order(published_on asc)[0...5]`
665
- return fetchSanity(config, query);
804
+ const query = `*[railcontent_id == ${railContentId} &amp;&amp; brand == "${brand}" &amp;&amp; references(*[_type=='permission']._id)]{
805
+ "related_lessons" : array::unique([
806
+ ...(*[_type=="song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^.artist->_id)]{_id, "id":railcontent_id, published_on, title, "thumbnail_url":thumbnail.asset->url, difficulty_string, railcontent_id, artist->}[0...11]),
807
+ ...(*[_type=="song" &amp;&amp; brand == "${brand}" &amp;&amp; references(^.genre[]->_id)]{_id, "id":railcontent_id, published_on, title, "thumbnail_url":thumbnail.asset->url, difficulty_string, railcontent_id, artist->}[0...11])
808
+ ])|order(published_on, railcontent_id)[0...11]}`;
809
+ return fetchSanity(query, false);
666
810
  }
667
811
 
668
812
  /**
669
813
  * Fetch all content for a specific pack by Railcontent ID.
670
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
671
814
  * @param {string} railcontentId - The Railcontent ID of the pack.
672
815
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack content data or null if not found.
673
816
  */
674
- export async function fetchPackAll(config, railcontentId) {
817
+ async function fetchPackAll(railcontentId) {
675
818
  //TODO: Implement getPacks
676
819
  const query = `*[_railcontent_id == ${railcontentId}]{
677
820
  railcontent_id,
@@ -684,38 +827,39 @@ export async function fetchPackAll(config, railcontentId) {
684
827
  web_url_path,
685
828
  published_on
686
829
  } | order(published_on asc)[0...5]`
687
- return fetchSanity(config, query);
830
+ return fetchSanity(query, true);
688
831
  }
689
832
 
690
833
  /**
691
834
  * Fetch all children of a specific pack by Railcontent ID.
692
- * @param {Object} config - Configuration object containing token, projectId, dataset, version, and debug.
693
835
  * @param {string} railcontentId - The Railcontent ID of the pack.
694
836
  * @returns {Promise&lt;Array&lt;Object>|null>} - The fetched pack children data or null if not found.
695
837
  */
696
- export async function fetchPackChildren(config, railcontentId) {
838
+ async function fetchPackChildren(railcontentId) {
697
839
  return fetchChildren(railcontentId, 'pack');
698
840
  }
699
841
 
700
842
  /**
701
843
  * Fetch data from the Sanity API based on a provided query.
702
- * @param {Object} config - Configuration object containing the Sanity API settings.
703
- * @param {string} config.token - The API token for authenticating with Sanity.
704
- * @param {string} config.projectId - The project ID in Sanity.
705
- * @param {string} config.dataset - The dataset name in Sanity.
706
- * @param {string} config.version - The API version to use.
707
- * @param {boolean} [config.debug=false] - Flag to enable debug mode, which logs the query and results.
708
844
  * @param {string} query - The GROQ query to execute against the Sanity API.
845
+ * @param {boolean} isList - Whether to return an array or single result
709
846
  * @returns {Promise&lt;Object|null>} - The first result from the query, or null if an error occurs or no results are found.
710
847
  */
711
- async function fetchSanity({ token, projectId, dataset, version, debug = false }, query, isList = false) {
712
- if (debug) {
848
+ async function fetchSanity(query, isList) {
849
+ // Check the config object before proceeding
850
+ if (!checkConfig(globalConfig)) {
851
+ return null;
852
+ }
853
+
854
+ if (globalConfig.debug) {
713
855
  console.log("fetchSanity Query:", query);
714
856
  }
857
+
715
858
  const encodedQuery = encodeURIComponent(query);
716
- const url = `https://${projectId}.apicdn.sanity.io/v${version}/data/query/${dataset}?query=${encodedQuery}`;
859
+ const api = globalConfig.useCachedAPI ? 'apicdn' : 'api'
860
+ const url = `https://${globalConfig.projectId}.${api}.sanity.io/v${globalConfig.version}/data/query/${globalConfig.dataset}?query=${encodedQuery}`;
717
861
  const headers = {
718
- 'Authorization': `Bearer ${token}`,
862
+ 'Authorization': `Bearer ${globalConfig.token}`,
719
863
  'Content-Type': 'application/json'
720
864
  };
721
865
 
@@ -723,19 +867,21 @@ async function fetchSanity({ token, projectId, dataset, version, debug = false }
723
867
  const response = await fetch(url, {headers});
724
868
  const result = await response.json();
725
869
  if (result.result) {
726
- if (debug) {
727
- console.log("fetchSanity Results:", result.result);
870
+ if (globalConfig.debug) {
871
+ console.log("fetchSanity Results:", result);
728
872
  }
729
873
  return isList ? result.result : result.result[0];
730
874
  } else {
731
875
  throw new Error('No results found');
732
876
  }
733
877
  } catch (error) {
734
- console.error('sanityQueryService: Fetch error:', error);
878
+ console.error('fetchSanity: Fetch error:', error);
735
879
  return null;
736
880
  }
737
881
  }
738
882
 
883
+
884
+ //Helper Functions
739
885
  function arrayJoinWithQuotes(array, delimiter = ',') {
740
886
  const wrapped = array.map(value => `'${value}'`);
741
887
  return wrapped.join(delimiter)
@@ -745,6 +891,53 @@ function getSanityDate(date) {
745
891
  return date.toISOString();
746
892
  }
747
893
 
894
+ function checkConfig(config) {
895
+ if (!config.token) {
896
+ console.warn('fetchSanity: The "token" property is missing in the config object.');
897
+ return false;
898
+ }
899
+ if (!config.projectId) {
900
+ console.warn('fetchSanity: The "projectId" property is missing in the config object.');
901
+ return false;
902
+ }
903
+ if (!config.dataset) {
904
+ console.warn('fetchSanity: The "dataset" property is missing in the config object.');
905
+ return false;
906
+ }
907
+ if (!config.version) {
908
+ console.warn('fetchSanity: The "version" property is missing in the config object.');
909
+ return false;
910
+ }
911
+ return true;
912
+ }
913
+
914
+
915
+ //Main
916
+ module.exports = {
917
+ initializeSanityService,
918
+ fetchSongById,
919
+ fetchArtists,
920
+ fetchSongArtistCount,
921
+ fetchRelatedSongs,
922
+ fetchAllSongs,
923
+ fetchSongFilterOptions,
924
+ fetchSongCount,
925
+ fetchWorkouts,
926
+ fetchNewReleases,
927
+ fetchUpcomingEvents,
928
+ fetchByRailContentId,
929
+ fetchByRailContentIds,
930
+ fetchAll,
931
+ fetchAllFilterOptions,
932
+ fetchMethodNextLesson,
933
+ fetchMethodChildren,
934
+ fetchNextPreviousLesson,
935
+ fetchRelatedLessons,
936
+ fetchPackAll,
937
+ fetchPackChildren,
938
+ fetchLessonContent
939
+ };
940
+
748
941
  </code></pre>
749
942
  </article>
750
943
  </section>
@@ -757,7 +950,7 @@ function getSanityDate(date) {
757
950
  <br class="clear">
758
951
 
759
952
  <footer>
760
- Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Aug 09 2024 20:57:53 GMT+0000 (Coordinated Universal Time) using the Minami theme.
953
+ Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Mon Aug 12 2024 13:37:15 GMT+0000 (Coordinated Universal Time) using the Minami theme.
761
954
  </footer>
762
955
 
763
956
  <script>prettyPrint();</script>