musora-content-services 1.0.104 → 1.0.107

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.
@@ -0,0 +1,122 @@
1
+
2
+
3
+ export class FilterBuilder {
4
+
5
+ STATUS_SCHEDULED = 'scheduled';
6
+
7
+ constructor(
8
+ filter = '',
9
+ {
10
+ user = undefined,
11
+ availableContentStatuses = [],
12
+ bypassPermissions = false,
13
+ pullFutureContent = false,
14
+ getFutureContentOnly = false,
15
+ getFutureScheduledContentsOnly = false,
16
+
17
+ }={}) {
18
+ this.user = user;
19
+ this.availableContentStatuses = availableContentStatuses;
20
+ this.bypassPermissions = bypassPermissions;
21
+ this.pullFutureContent = pullFutureContent;
22
+ this.getFutureContentOnly = getFutureContentOnly;
23
+ this.getFutureScheduledContentsOnly = getFutureScheduledContentsOnly;
24
+ this.filter = filter;
25
+ this.debug = process.env.DEBUG === 'true' || false;
26
+ }
27
+
28
+
29
+ static withOnlyFilterAvailableStatuses(filter, availableContentStatuses) {
30
+ return new FilterBuilder(filter,{
31
+ availableContentStatuses,
32
+ });
33
+ }
34
+
35
+ buildFilter() {
36
+ if (this.debug) console.log('baseFilter', this.filter);
37
+ const filter = this
38
+ ._applyContentStatuses()
39
+ ._applyPermissions()
40
+ ._applyPublishingDateRestrictions()
41
+ ._trimAmpersands() // just in case
42
+ .filter;
43
+ if (this.debug) console.log('finalFilter', filter);
44
+ return filter;
45
+ }
46
+
47
+ _applyContentStatuses() {
48
+ // This must be run before _applyPublishDateRestrictions()
49
+ if (this.availableContentStatuses.length === 0) return this;
50
+ // I'm not sure if I'm 100% on this logic, but this is my intepretation of the ContentRepository logic
51
+ if (this.getFutureScheduledContentsOnly && this.availableContentStatuses.includes(this.STATUS_SCHEDULED)) {
52
+ // we must pull in future content here, otherwise we'll restrict on content this is published in the past and remove any scheduled content
53
+ this.pullFutureContent = true;
54
+ const now = new Date().toISOString();
55
+ let statuses = [...this.availableContentStatuses];
56
+ statuses.splice(statuses.indexOf(this.STATUS_SCHEDULED));
57
+ this._andWhere(`(status in ${arrayToStringRepresentation(statuses)} || (status == '${this.STATUS_SCHEDULED}' && published_on >= '${now}'))`)
58
+
59
+ } else {
60
+ this._andWhere(`status in ${arrayToStringRepresentation(this.availableContentStatuses)}`);
61
+ }
62
+ return this;
63
+ }
64
+
65
+ _applyPermissions() {
66
+ if (this.bypassPermissions) return this;
67
+ // TODO these need to be pulled from the user and reference either ID, or railcontent_id
68
+ const requiredPermissions = this._getUserPermissions();
69
+ if (requiredPermissions.length === 0) return this;
70
+ // handle pullSongsContent, I think the flagging on this needs to be backwards compared to BE
71
+ // if using id, switch railcontent_id to _id in the below query
72
+ this._andWhere(`references(*[_type == 'permission' && railcontent_id in ${arrayToRawRepresentation(requiredPermissions)}]._id)`);
73
+ return this;
74
+
75
+ }
76
+
77
+ _getUserPermissions() {
78
+ // TODO need user store up and running to complete this, until then just null check
79
+ return this?.user?.permissions ?? [];
80
+ }
81
+
82
+ _applyPublishingDateRestrictions() {
83
+ const now = new Date().toISOString();
84
+ if (this.getFutureContentOnly) {
85
+ this._andWhere(`published_on >= '${now}'`);
86
+ } else if (!this.pullFutureContent) {
87
+ this._andWhere(`published_on <= '${now}'`);
88
+ } else {
89
+ const date = new Date();
90
+ const theFuture = new Date(date.setMonth(date.getMonth() + 18));
91
+ this._andWhere(`published_on <= '${theFuture}'`);
92
+ }
93
+ return this;
94
+ }
95
+
96
+ _andWhere(query) {
97
+ const leadingAmpersand = this.filter ? ' && ' : '';
98
+ this.filter += leadingAmpersand + query;
99
+ }
100
+
101
+ _orWhere(query) {
102
+ if (!this.filter) throw new Error("invalid query, _orWhere needs to be called on an existing query");
103
+ this.filter += ` || (${query})`;
104
+ }
105
+
106
+ _trimAmpersands() {
107
+ this.filter = this.filter.trim();
108
+ while( this.filter.charAt(0) === '&' || this.filter.charAt(0) === ' ' ) this.filter = this.filter.substring(1);
109
+ while( this.filter.charAt(this.filter.length) === '&' || this.filter.charAt(this.filter.length) === ' ' ) this.filter = this.filter.slice(-1);
110
+ return this;
111
+ }
112
+
113
+
114
+ }
115
+
116
+ export function arrayToStringRepresentation(arr) {
117
+ return '[' + arr.map(item => `'${item}'`).join(',') + ']';
118
+ }
119
+
120
+ export function arrayToRawRepresentation(arr) {
121
+ return '[' + arr.map(item => `${item}`).join(',') + ']';
122
+ }
@@ -150,15 +150,15 @@ export async function fetchSongsInProgress(brand) {
150
150
  * .then(songs => console.log(songs))
151
151
  * .catch(error => console.error(error));
152
152
  */
153
- export async function fetchContentInProgress(type="all", brand, {
154
- page = 1,
155
- limit = 10,
156
- } = {}) {
153
+ export async function fetchContentInProgress(type="all", brand, { page, limit } = {}) {
157
154
  let url;
155
+ const limitString = limit ? `&limit=${limit}` : '';
156
+ const pageString = page ? `&page=${page}` : '';
157
+
158
158
  if(type === "all") {
159
- url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?brand=${brand}&limit=${limit}&page=${page}`;
159
+ url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?brand=${brand}${limitString}${pageString}`;
160
160
  } else {
161
- url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}&limit=${limit}&page=${page}`;
161
+ url = `/content/in_progress/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}${limitString}${pageString}`;
162
162
  }
163
163
  const headers = {
164
164
  'Content-Type': 'application/json',
@@ -192,15 +192,15 @@ export async function fetchContentInProgress(type="all", brand, {
192
192
  * .then(songs => console.log(songs))
193
193
  * .catch(error => console.error(error));
194
194
  */
195
- export async function fetchCompletedContent(type="all", brand, {
196
- page = 1,
197
- limit = 10,
198
- } = {}) {
195
+ export async function fetchCompletedContent(type="all", brand, { page, limit } = {}) {
199
196
  let url;
197
+ const limitString = limit ? `&limit=${limit}` : '';
198
+ const pageString = page ? `&page=${page}` : '';
199
+
200
200
  if(type === "all") {
201
- url = `/content/completed/${globalConfig.railcontentConfig.userId}?brand=${brand}&limit=${limit}&page=${page}`;
201
+ url = `/content/completed/${globalConfig.railcontentConfig.userId}?brand=${brand}${limitString}${pageString}`;
202
202
  } else {
203
- url = `/content/completed/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}&limit=${limit}&page=${page}`;
203
+ url = `/content/completed/${globalConfig.railcontentConfig.userId}?content_type=${type}&brand=${brand}${limitString}${pageString}`;
204
204
  }
205
205
  const headers = {
206
206
  'Content-Type': 'application/json',