musora-content-services 1.0.116 → 1.0.119

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.
@@ -301,15 +301,6 @@ export async function fetchContentPageUserData(contentId) {
301
301
  }
302
302
  }
303
303
 
304
- function fetchAbsolute(url, params) {
305
- if(globalConfig.railcontentConfig.baseUrl) {
306
- if (url.startsWith('/')) {
307
- return fetch(globalConfig.railcontentConfig.baseUrl + url, params)
308
- }
309
- }
310
- return fetch(url, params);
311
- }
312
-
313
304
  export async function fetchUserContext() {
314
305
  let url = `/content/user_data_all`;
315
306
  const headers = {
@@ -317,7 +308,7 @@ export async function fetchUserContext() {
317
308
  'X-CSRF-TOKEN': globalConfig.railcontentConfig.token
318
309
  };
319
310
  try {
320
- const response = await fetch(url, {headers});
311
+ const response = await fetchAbsolute(url, {headers});
321
312
  const result = await response.json();
322
313
  if (result) {
323
314
  console.log('fetchUserContext', result);
@@ -331,13 +322,25 @@ export async function fetchUserContext() {
331
322
  }
332
323
  }
333
324
 
325
+ export async function fetchUserPermissions() {
326
+ //TODO: Should be investigate why throw 500 errors on MA
327
+ return [];
328
+ let url = `/content/user_data_permissions`;
329
+ const headers = {
330
+ 'Content-Type': 'application/json',
331
+ 'X-CSRF-TOKEN': globalConfig.railcontentConfig.token
332
+ };
333
+ // in the case of an unauthorized user, we return empty permissions
334
+ return fetchHandler(url, 'get') ?? [];
335
+ }
336
+
334
337
  export async function fetchHandler(url, method = "get") {
335
338
  const headers = {
336
339
  'Content-Type': 'application/json',
337
340
  'X-CSRF-TOKEN': globalConfig.railcontentConfig.token
338
341
  };
339
342
  try {
340
- const response = await fetch(url, {method, headers});
343
+ const response = await fetchAbsolute(url, {method, headers});
341
344
  const result = await response.json();
342
345
  if (result) {
343
346
  return result;
@@ -346,8 +349,8 @@ export async function fetchHandler(url, method = "get") {
346
349
  }
347
350
  } catch (error) {
348
351
  console.error('Fetch error:', error);
349
- return null;
350
352
  }
353
+ return null;
351
354
  }
352
355
 
353
356
  export async function fetchLikeContent(contentId) {
@@ -358,6 +361,15 @@ export async function fetchLikeContent(contentId) {
358
361
  export async function fetchUnlikeContent(contentId) {
359
362
  let url = `/content/${contentId}/unlike`;
360
363
  return await fetchHandler(url, "post");
364
+ }
365
+
366
+ function fetchAbsolute(url, params) {
367
+ if(globalConfig.railcontentConfig.baseUrl) {
368
+ if (url.startsWith('/')) {
369
+ return fetch(globalConfig.railcontentConfig.baseUrl + url, params)
370
+ }
371
+ }
372
+ return fetch(url, params);
361
373
  }</code></pre>
362
374
  </article>
363
375
  </section>
@@ -372,7 +384,7 @@ export async function fetchUnlikeContent(contentId) {
372
384
  <br class="clear">
373
385
 
374
386
  <footer>
375
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Tue Sep 24 2024 20:13:55 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
387
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Sep 27 2024 21:58:51 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
376
388
  </footer>
377
389
 
378
390
  <script>prettyPrint();</script>
@@ -58,13 +58,17 @@ import {
58
58
  getFieldsForContentType,
59
59
  filtersToGroq,
60
60
  getUpcomingEventsTypes,
61
- getNewReleasesTypes,
62
61
  showsTypes,
63
- contentMetadata
62
+ getNewReleasesTypes,
64
63
  } from "../contentTypeConfig";
64
+
65
+ import {
66
+ processMetadata,
67
+ } from "../contentMetaData";
68
+
65
69
  import {globalConfig} from "./config";
66
70
 
67
- import { fetchAllCompletedStates, fetchCurrentSongComplete } from './railcontent.js';
71
+ import { fetchUserPermissions, fetchAllCompletedStates, fetchCurrentSongComplete } from './railcontent.js';
68
72
  import {arrayToStringRepresentation, FilterBuilder} from "../filterBuilder";
69
73
 
70
74
  /**
@@ -264,8 +268,7 @@ export async function fetchSongFilterOptions(brand) {
264
268
  {"type": "Full Song Only", "count": count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; instrumentless == false]._id)},
265
269
  {"type": "Instrument Removed", "count": count(*[_type == 'song' &amp;&amp; brand == '${brand}' &amp;&amp; instrumentless == true]._id)}
266
270
  ]
267
- }
268
- `;
271
+ }`;
269
272
 
270
273
  return fetchSanity(query, true);
271
274
  }
@@ -543,58 +546,51 @@ export async function fetchAll(brand, type, {
543
546
 
544
547
  // Determine the group by clause
545
548
  let query = "";
549
+ let entityFieldsString = "";
550
+ let filter = "";
546
551
  if (groupBy !== "" &amp;&amp; isGroupByOneToOne) {
547
- let webUrlPath = 'artists';
548
- query = `
549
- {
550
- "total": count(*[_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
551
- "entity": *[_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
552
- {
552
+ const webUrlPath = 'artists';
553
+ const lessonsFilter = `_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}`;
554
+ entityFieldsString = `
553
555
  'id': _id,
554
556
  'type': _type,
555
557
  name,
556
558
  'head_shot_picture_url': thumbnail_url.asset->url,
557
559
  'web_url_path': '/${brand}/${webUrlPath}/'+name+'?included_fieds[]=type,${type}',
558
- 'all_lessons_count': count(*[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
559
- 'lessons': *[_type == '${type}' &amp;&amp; brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
560
+ 'all_lessons_count': count(*[${lessonsFilter}]._id),
561
+ 'lessons': *[${lessonsFilter}]{
560
562
  ${fieldsString},
561
563
  ${groupBy}
562
564
  }[0...20]
563
- }
564
- |order(${sortOrder})
565
- [${start}...${end}]
566
- }`;
565
+ `;
566
+ filter = `_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id == ${groupBy}._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0`;
567
567
  } else if (groupBy !== "") {
568
- let webUrlPath = (groupBy == 'genre')?'/genres':'';
569
- query = `
570
- {
571
- "total": count(*[_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]),
572
- "entity": *[_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0]
573
- {
568
+ const webUrlPath = (groupBy == 'genre')?'/genres':'';
569
+ const lessonsFilter = `brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}`;
570
+ entityFieldsString = `
574
571
  'id': _id,
575
572
  'type': _type,
576
573
  name,
577
574
  'head_shot_picture_url': thumbnail_url.asset->url,
578
575
  'web_url_path': select(defined(web_url_path)=> web_url_path +'?included_fieds[]=type,${type}',!defined(web_url_path)=> '/${brand}${webUrlPath}/'+name+'/${webUrlPathType}'),
579
- 'all_lessons_count': count(*[brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id),
580
- 'lessons': *[brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]{
576
+ 'all_lessons_count': count(*[${lessonsFilter}]._id),
577
+ 'lessons': *[${lessonsFilter}]{
581
578
  ${fieldsString},
582
579
  ${groupBy}
583
- }[0...20]
584
- }
585
- |order(${sortOrder})
586
- [${start}...${end}]
587
- }`;
580
+ }[0...20]`;
581
+ filter = `_type == '${groupBy}' &amp;&amp; count(*[brand == '${brand}' &amp;&amp; ^._id in ${groupBy}[]._ref ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}]._id) > 0`;
588
582
  } else {
589
- query = `
590
- {
591
- "entity": *[brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}] | order(${sortOrder}) [${start}...${end}] {
592
- ${fieldsString},
593
- },
594
- "total": count(*[brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}])
595
- }
596
- `;
583
+ filter = `brand == "${brand}" ${typeFilter} ${searchFilter} ${includedFieldsFilter} ${progressFilter}`
584
+ entityFieldsString = fieldsString;
597
585
  }
586
+ query = buildEntityAndTotalQuery(
587
+ filter,
588
+ entityFieldsString,
589
+ {
590
+ sortOrder: sortOrder,
591
+ start: start,
592
+ end: end,
593
+ });
598
594
 
599
595
  return fetchSanity(query, true);
600
596
  }
@@ -645,40 +641,39 @@ export function getSortOrder(sort= '-published_on', groupBy)
645
641
  */
646
642
  export async function fetchAllFilterOptions(
647
643
  brand,
648
- filters,
644
+ filters = [],
649
645
  style,
650
646
  artist,
651
647
  contentType,
652
648
  term,
653
649
  progressIds = undefined
654
650
  ) {
651
+ filters = Array.isArray(filters) ? filters : [];
655
652
  const includedFieldsFilter = filters?.length > 0 ? filtersToGroq(filters) : undefined;
656
653
 
657
654
  const progressFilter = progressIds !== undefined ?
658
655
  `&amp;&amp; railcontent_id in [${progressIds.join(',')}]` : "";
659
656
 
660
657
  const commonFilter = `_type == '${contentType}' &amp;&amp; brand == "${brand}"${style ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${artist ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${progressFilter} ${includedFieldsFilter ? includedFieldsFilter : ''}`;
658
+ const metaData = processMetadata(brand, contentType, true);
659
+ const allowableFilters = metaData?.allowableFilters || [];
660
+
661
+ const dynamicFilterOptions = allowableFilters.map(filter => {
662
+ // Create a modified common filter for each allowable filter
663
+ let includedFieldsFilterWithoutSelectedOption = filters?.length > 0 ? filtersToGroq(filters, filter) : undefined;
664
+ const commonFilterWithoutSelectedOption = `_type == '${contentType}' &amp;&amp; brand == "${brand}"${(style &amp;&amp; filter !== "style") ? ` &amp;&amp; '${style}' in genre[]->name` : ''}${(artist &amp;&amp; filter !== "artist") ? ` &amp;&amp; artist->name == '${artist}'` : ''} ${includedFieldsFilterWithoutSelectedOption ? includedFieldsFilterWithoutSelectedOption : ''}`;
665
+
666
+ // Call getFilterOptions with the modified common filter
667
+ return getFilterOptions(filter, commonFilterWithoutSelectedOption, contentType);
668
+ }).join(' ');
669
+
661
670
  const query = `
662
671
  {
663
672
  "meta": {
664
673
  "totalResults": count(*[${commonFilter}
665
674
  ${term ? ` &amp;&amp; (title match "${term}" || album match "${term}" || artist->name match "${term}" || genre[]->name match "${term}")` : ''}]),
666
675
  "filterOptions": {
667
- "difficulty": [
668
- {"type": "Introductory", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Introductory"])},
669
- {"type": "Beginner", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Beginner"])},
670
- {"type": "Intermediate", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Intermediate" ])},
671
- {"type": "Advanced", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Advanced" ])},
672
- {"type": "Expert", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Expert" ])}
673
- ][count > 0],
674
- "instrumentless": [
675
- {"type": "Full Song Only", "count": count(*[${commonFilter} &amp;&amp; instrumentless == false ])},
676
- {"type": "Instrument Removed", "count": count(*[${commonFilter} &amp;&amp; instrumentless == true ])}
677
- ][count > 0],
678
- "genre": *[_type == 'genre' &amp;&amp; '${contentType}' in filter_types] {
679
- "type": name,
680
- "count": count(*[${commonFilter} &amp;&amp; references(^._id)])
681
- }[count > 0]
676
+ ${dynamicFilterOptions}
682
677
  }
683
678
  }
684
679
  }`;
@@ -877,8 +872,6 @@ function getChildrenToDepth(parent, depth = 1)
877
872
  return allChildrenIds;
878
873
  }
879
874
 
880
-
881
-
882
875
  /**
883
876
  * Fetch the next and previous lessons for a specific lesson by Railcontent ID.
884
877
  * @param {string} railcontentId - The Railcontent ID of the current lesson.
@@ -1021,13 +1014,15 @@ export async function fetchAllPacks(brand, sort = "-published_on", searchTerm =
1021
1014
  const sortOrder = getSortOrder(sort);
1022
1015
  const filter = `_type == 'pack' &amp;&amp; brand == '${brand}' &amp;&amp; title match "${searchTerm}*"`
1023
1016
  const filterParams = {};
1017
+ const fields = getFieldsForContentType('pack');
1024
1018
  const query = buildQuery(
1025
1019
  filter,
1026
1020
  filterParams,
1027
1021
  getFieldsForContentType('pack'),
1028
- {
1029
- sortOrder: sortOrder,
1030
- }
1022
+ {
1023
+ logo_image_url: 'logo_image_url.asset->url',
1024
+ sortOrder: sortOrder,
1025
+ }
1031
1026
  );
1032
1027
  return fetchSanity(query, true);
1033
1028
  }
@@ -1298,13 +1293,13 @@ export async function fetchGenreLessons(brand, name, contentType, {
1298
1293
  }
1299
1294
 
1300
1295
 
1301
-
1302
1296
  /**
1303
- * Fetch data from the Sanity API based on a provided query.
1304
1297
  *
1305
1298
  * @param {string} query - The GROQ query to execute against the Sanity API.
1306
1299
  * @param {boolean} isList - Whether to return an array or a single result.
1307
- * @returns {Promise&lt;Object|null>} - A promise that resolves to the fetched data or null if an error occurs or no results are found.
1300
+ * @param {Function} [customPostProcess=null] - custom post process callback
1301
+ * @param {boolean} [processNeedAccess=true] - execute the needs_access callback
1302
+ * @returns {Promise&lt;*|null>} - A promise that resolves to the fetched data or null if an error occurs or no results are found.
1308
1303
  *
1309
1304
  * @example
1310
1305
  * const query = `*[_type == "song"]{title, artist->name}`;
@@ -1312,7 +1307,13 @@ export async function fetchGenreLessons(brand, name, contentType, {
1312
1307
  * .then(data => console.log(data))
1313
1308
  * .catch(error => console.error(error));
1314
1309
  */
1315
- export async function fetchSanity(query, isList) {
1310
+
1311
+ export async function fetchSanity(query,
1312
+ isList,
1313
+ { customPostProcess = null,
1314
+ processNeedAccess = true,} = {}
1315
+ ) {
1316
+
1316
1317
  // Check the config object before proceeding
1317
1318
  if (!checkSanityConfig(globalConfig)) {
1318
1319
  return null;
@@ -1340,7 +1341,9 @@ export async function fetchSanity(query, isList) {
1340
1341
  if (globalConfig.sanityConfig.debug) {
1341
1342
  console.log("fetchSanity Results:", result);
1342
1343
  }
1343
- return isList ? result.result : result.result[0];
1344
+ let results = isList ? result.result : result.result[0];
1345
+ results = processNeedAccess ? await needsAccessDecorator(results) : results;
1346
+ return customPostProcess ? customPostProcess(results) : results;
1344
1347
  } else {
1345
1348
  throw new Error('No results found');
1346
1349
  }
@@ -1350,6 +1353,41 @@ export async function fetchSanity(query, isList) {
1350
1353
  }
1351
1354
  }
1352
1355
 
1356
+ async function needsAccessDecorator(results)
1357
+ {
1358
+ if (globalConfig.sanityConfig.useDummyRailContentMethods) return results;
1359
+ let userPermissions = await getUserPermissions();
1360
+ userPermissions = new Set(userPermissions);
1361
+ if (Array.isArray(results)) {
1362
+ results.forEach((result) => {
1363
+ result['need_access'] = doesUserNeedAccessToContent(result, userPermissions);
1364
+ });
1365
+ } else {
1366
+ results['need_access'] = doesUserNeedAccessToContent(results, userPermissions);
1367
+ }
1368
+ return results;
1369
+ }
1370
+
1371
+ function doesUserNeedAccessToContent(result, userPermissions)
1372
+ {
1373
+ const permissions = new Set(result.permission_id ?? []);
1374
+ if (permissions.length === 0) {
1375
+ return false;
1376
+ }
1377
+ for (let permission of permissions) {
1378
+ if (userPermissions.has(permission)) {
1379
+ return false;
1380
+ }
1381
+ }
1382
+ return true;
1383
+ }
1384
+
1385
+ async function getUserPermissions()
1386
+ {
1387
+ return await fetchUserPermissions();
1388
+ }
1389
+
1390
+
1353
1391
  /**
1354
1392
  * Fetch CatalogueMetadata from Sanity. This information may be duplicated in the contentTypeConfig.js.
1355
1393
  * It's an ongoing discussion (Aug 2024), but it's been included here if necessary
@@ -1401,7 +1439,7 @@ export async function fetchShowsData(brand) {
1401
1439
  }
1402
1440
 
1403
1441
  /**
1404
- * Fetch metadata from the contentTypeConfig.js based on brand and type.
1442
+ * Fetch metadata from the contentMetaData.js based on brand and type.
1405
1443
  *
1406
1444
  * @param {string} brand - The brand for which to fetch metadata.
1407
1445
  * @param {string} type - The type for which to fetch metadata.
@@ -1512,27 +1550,88 @@ function buildEntityAndTotalQuery(
1512
1550
  }`;
1513
1551
  return query;
1514
1552
  }
1515
- function processMetadata(brand, type, withFilters = false) {
1516
- const metadataElement = contentMetadata[brand]?.[type];
1517
- if (!metadataElement) {
1518
- return null;
1553
+
1554
+
1555
+ function getFilterOptions(option, commonFilter,contentType){
1556
+ let filterGroq = '';
1557
+ switch (option) {
1558
+ case "difficulty":
1559
+ filterGroq = `
1560
+ "difficulty": [
1561
+ {"type": "Introductory", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Introductory"])},
1562
+ {"type": "Beginner", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Beginner"])},
1563
+ {"type": "Intermediate", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Intermediate" ])},
1564
+ {"type": "Advanced", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Advanced" ])},
1565
+ {"type": "Expert", "count": count(*[${commonFilter} &amp;&amp; difficulty_string == "Expert" ])}
1566
+ ][count > 0],`;
1567
+ break;
1568
+ case "genre":
1569
+ case "essential":
1570
+ case "focus":
1571
+ case "theory":
1572
+ case "topic":
1573
+ case "lifestyle":
1574
+ case "creativity":
1575
+ filterGroq = `
1576
+ "${option}": *[_type == '${option}' &amp;&amp; '${contentType}' in filter_types] {
1577
+ "type": name,
1578
+ "count": count(*[${commonFilter} &amp;&amp; references(^._id)])
1579
+ }[count > 0],`;
1580
+ break;
1581
+ case "instrumentless":
1582
+ filterGroq = `
1583
+ "${option}": [
1584
+ {"type": "Full Song Only", "count": count(*[${commonFilter} &amp;&amp; instrumentless == false ])},
1585
+ {"type": "Instrument Removed", "count": count(*[${commonFilter} &amp;&amp; instrumentless == true ])}
1586
+ ][count > 0],`;
1587
+ break;
1588
+ case "gear":
1589
+ filterGroq = `
1590
+ "${option}": [
1591
+ {"type": "Practice Pad", "count": count(*[${commonFilter} &amp;&amp; gear match 'Practice Pad' ])},
1592
+ {"type": "Drum-Set", "count": count(*[${commonFilter} &amp;&amp; gear match 'Drum-Set'])}
1593
+ ][count > 0],`;
1594
+ break;
1595
+ case "bpm":
1596
+ filterGroq = `
1597
+ "${option}": [
1598
+ {"type": "50-90", "count": count(*[${commonFilter} &amp;&amp; bpm > 50 &amp;&amp; bpm &lt; 91])},
1599
+ {"type": "91-120", "count": count(*[${commonFilter} &amp;&amp; bpm > 90 &amp;&amp; bpm &lt; 121])},
1600
+ {"type": "121-150", "count": count(*[${commonFilter} &amp;&amp; bpm > 120 &amp;&amp; bpm &lt; 151])},
1601
+ {"type": "151-180", "count": count(*[${commonFilter} &amp;&amp; bpm > 150 &amp;&amp; bpm &lt; 181])},
1602
+ {"type": "180+", "count": count(*[${commonFilter} &amp;&amp; bpm > 180])},
1603
+ ][count > 0],`;
1604
+ break;
1605
+ default:
1606
+ filterGroq = "";
1607
+ break;
1519
1608
  }
1520
- const processedData = {
1521
- type,
1522
- thumbnailUrl: metadataElement.thumbnailUrl || null,
1523
- name: metadataElement.name || null,
1524
- description: metadataElement.description || null
1525
- };
1526
-
1527
- if (withFilters) {
1528
- Object.keys(metadataElement).forEach(key => {
1529
- if ( !['thumbnailUrl', 'name', 'description'].includes(key) ) {
1530
- processedData[key] = metadataElement[key];
1531
- }
1532
- });
1609
+
1610
+ return filterGroq;
1611
+ }
1612
+
1613
+ function cleanUpGroq(query) {
1614
+ // Split the query into clauses based on the logical operators
1615
+ const clauses = query.split(/(\s*&amp;&amp;|\s*\|\|)/).map(clause => clause.trim());
1616
+
1617
+ // Filter out empty clauses
1618
+ const filteredClauses = clauses.filter(clause => clause.length > 0);
1619
+
1620
+ // Check if there are valid conditions in the clauses
1621
+ const hasConditions = filteredClauses.some(clause => !clause.match(/^\s*&amp;&amp;\s*|\s*\|\|\s*$/));
1622
+
1623
+ if (!hasConditions) {
1624
+ // If no valid conditions, return an empty string or the original query
1625
+ return '';
1533
1626
  }
1534
1627
 
1535
- return processedData;
1628
+ // Remove occurrences of '&amp;&amp; ()'
1629
+ const cleanedQuery = filteredClauses.join(' ')
1630
+ .replace(/&amp;&amp;\s*\(\)/g, '')
1631
+ .replace(/(\s*&amp;&amp;|\s*\|\|)(?=\s*[\s()]*$|(?=\s*&amp;&amp;|\s*\|\|))/g, '')
1632
+ .trim();
1633
+
1634
+ return cleanedQuery;
1536
1635
  }
1537
1636
 
1538
1637
 
@@ -1553,7 +1652,7 @@ function processMetadata(brand, type, withFilters = false) {
1553
1652
  <br class="clear">
1554
1653
 
1555
1654
  <footer>
1556
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Tue Sep 24 2024 20:13:55 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1655
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Fri Sep 27 2024 21:58:51 GMT+0000 (Coordinated Universal Time) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1557
1656
  </footer>
1558
1657
 
1559
1658
  <script>prettyPrint();</script>
package/link_mcs.sh CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "1.0.116",
3
+ "version": "1.0.119",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "scripts": {