musora-content-services 1.3.18 → 2.0.2

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 (46) hide show
  1. package/.editorconfig +16 -0
  2. package/CHANGELOG.md +1 -1
  3. package/docs/config.js.html +14 -5
  4. package/docs/content.js.html +425 -0
  5. package/docs/global.html +3026 -0
  6. package/docs/index.html +2 -2
  7. package/docs/module-Config.html +60 -7
  8. package/docs/module-Content-Services-V2.html +2433 -0
  9. package/docs/module-Railcontent-Services.html +522 -2
  10. package/docs/module-Sanity-Services.html +57 -43
  11. package/docs/module-Session-Management.html +575 -0
  12. package/docs/module-User-Permissions.html +406 -0
  13. package/docs/railcontent.js.html +42 -5
  14. package/docs/sanity.js.html +290 -103
  15. package/docs/user_permissions.js.html +110 -0
  16. package/docs/user_sessions.js.html +139 -0
  17. package/docs/user_types.js.html +188 -0
  18. package/jsdoc.json +2 -0
  19. package/package.json +1 -1
  20. package/publish.sh +2 -2
  21. package/src/contentMetaData.js +307 -1088
  22. package/src/contentTypeConfig.js +108 -4
  23. package/src/filterBuilder.js +6 -6
  24. package/src/index.d.ts +41 -6
  25. package/src/index.js +41 -6
  26. package/src/{services → lib}/lastUpdated.js +17 -1
  27. package/src/services/config.js +0 -0
  28. package/src/services/content.js +371 -0
  29. package/src/services/dataContext.js +0 -0
  30. package/src/services/forum.js +57 -0
  31. package/src/services/railcontent.js +3 -3
  32. package/src/services/recommendations.js +19 -0
  33. package/src/services/sanity.js +278 -104
  34. package/src/services/{userPermissions.js → user/permissions.js} +16 -2
  35. package/src/services/user/sessions.js +67 -0
  36. package/src/services/user/types.js +116 -0
  37. package/src/services/userActivity.js +32 -0
  38. package/test/content.test.js +116 -0
  39. package/test/contentLikes.test.js +0 -0
  40. package/test/contentProgress.test.js +83 -5
  41. package/test/forum.test.js +18 -0
  42. package/test/initializeTests.js +6 -1
  43. package/test/{lastUpdated.test.js → lib/lastUpdated.test.js} +2 -5
  44. package/test/sanityQueryService.test.js +66 -18
  45. package/test/{userPermissions.test.js → user/permissions.test.js} +3 -3
  46. package/tools/generate-index.cjs +16 -3
@@ -1,4 +1,6 @@
1
1
  //import {AWSUrl, CloudFrontURl} from "./services/config";
2
+ import {Tabs} from "./contentMetaData.js";
3
+
2
4
  export const AWSUrl = 'https://s3.us-east-1.amazonaws.com/musora-web-platform'
3
5
  export const CloudFrontURl = 'https://d3fzm1tzeyr5n3.cloudfront.net'
4
6
  export const DEFAULT_FIELDS = [
@@ -25,6 +27,7 @@ export const DEFAULT_FIELDS = [
25
27
  "'permission_id': permission[]->railcontent_id",
26
28
  'xp',
27
29
  'child_count',
30
+ '"lesson_count": coalesce(count(child[]->.child[]->), child_count)',
28
31
  ]
29
32
  export const DEFAULT_CHILD_FIELDS = [
30
33
  `"id": railcontent_id`,
@@ -50,7 +53,7 @@ export const assignmentsField = `"assignments":assignment[]{
50
53
  "id": railcontent_id,
51
54
  "soundslice_slug": assignment_soundslice,
52
55
  "title": assignment_title,
53
- "sheet_music_image_url":
56
+ "sheet_music_image_url":
54
57
  coalesce(assignment_sheet_music_image_new[]{
55
58
  _type == 'Image' => {
56
59
  'url': asset->url
@@ -126,6 +129,62 @@ export const childContentTypeConfig = {
126
129
  ]
127
130
  }
128
131
 
132
+ export const singleLessonTypes = ['quick-tips', 'rudiment', 'coach-lessons'];
133
+ export const practiceAlongsLessonTypes = ['workout', 'boot-camp','challenges'];
134
+ export const performancesLessonTypes = ['performance','solo','drum-fest-international-2022'];
135
+ export const documentariesLessonTypes = ['tama','sonor','history-of-electronic-drums','paiste-cymbals'];
136
+ export const liveArchivesLessonTypes = ['podcast', 'coach-stream', 'live-streams'];
137
+ export const studentArchivesLessonTypes = ['student-review', 'question-and-answer', 'student-focus','student-collaborations'];
138
+ export const tutorialsLessonTypes = ['song-tutorial'];
139
+ export const transcriptionsLessonTypes = ['song'];
140
+ export const playAlongLessonTypes = ['play-along'];
141
+
142
+ export const individualLessonsTypes = [
143
+ ...singleLessonTypes,
144
+ ...practiceAlongsLessonTypes,
145
+ ...performancesLessonTypes,
146
+ ...documentariesLessonTypes,
147
+ ...liveArchivesLessonTypes,
148
+ ...studentArchivesLessonTypes
149
+ ];
150
+
151
+ export const coursesLessonTypes = ['course', 'pack','spotlight'];
152
+ export const showsLessonTypes = ['diy-drum-experiments','exploring-beats','in-rhythm', 'rhythmic-adventures-of-captain-carson','rhythms-from-another-planet','study-the-greats'];
153
+ export const collectionLessonTypes = [
154
+ ...coursesLessonTypes,
155
+ ...showsLessonTypes
156
+ ];
157
+
158
+ export const lessonTypesMapping = {
159
+ 'single lessons': singleLessonTypes,
160
+ 'practice alongs': practiceAlongsLessonTypes,
161
+ 'live archives': liveArchivesLessonTypes,
162
+ 'performances': performancesLessonTypes,
163
+ 'student archives': studentArchivesLessonTypes,
164
+ 'documentaries': documentariesLessonTypes,
165
+ 'courses': coursesLessonTypes,
166
+ 'shows': showsLessonTypes,
167
+ 'collections': collectionLessonTypes,
168
+ 'individuals': individualLessonsTypes,
169
+ 'tutorials': tutorialsLessonTypes,
170
+ 'transcriptions': transcriptionsLessonTypes,
171
+ 'tabs': transcriptionsLessonTypes,
172
+ 'sheet music': transcriptionsLessonTypes,
173
+ 'play alongs': playAlongLessonTypes,
174
+ };
175
+
176
+
177
+ export const filterTypes = {
178
+ lessons: [...individualLessonsTypes, ...collectionLessonTypes],
179
+ songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes]
180
+ }
181
+
182
+ export const recentTypes = {
183
+ lessons: [...individualLessonsTypes],
184
+ songs: [...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes],
185
+ home: [...individualLessonsTypes, ...tutorialsLessonTypes, ...transcriptionsLessonTypes, ...playAlongLessonTypes]
186
+ }
187
+
129
188
  export let contentTypeConfig = {
130
189
  song: {
131
190
  fields: ['album', 'soundslice', 'instrumentless', `"resources": ${resourcesField}`],
@@ -230,7 +289,7 @@ export let contentTypeConfig = {
230
289
  "instructors": instructor[]->name,
231
290
  length_in_seconds,
232
291
  "resources": ${resourcesField},
233
- difficulty,
292
+ difficulty,
234
293
  difficulty_string,
235
294
  artist->,
236
295
  "thumbnail_url":thumbnail.asset->url,
@@ -595,7 +654,7 @@ export function getChildFieldsForContentType(contentType, asQueryString = true)
595
654
  * 'genre,rock']
596
655
  * @returns {string} - A string that can be used in a groq query
597
656
  */
598
- export function filtersToGroq(filters, selectedFilters = []) {
657
+ export function filtersToGroq(filters, selectedFilters = [], pageName = '') {
599
658
  if (!filters) {
600
659
  filters = []
601
660
  }
@@ -639,6 +698,13 @@ export function filtersToGroq(filters, selectedFilters = []) {
639
698
  !selectedFilters.includes(key)
640
699
  ) {
641
700
  return `"${value}" in ${key}[]->name`
701
+ } else if (
702
+ ['style'].includes(
703
+ key
704
+ ) &&
705
+ !selectedFilters.includes(key)
706
+ ) {
707
+ return `"${value}" in genre[]->name`
642
708
  } else if (key === 'gear' && !selectedFilters.includes('gear')) {
643
709
  return `gear match "${value}"`
644
710
  } else if (key === 'instrumentless' && !selectedFilters.includes(key)) {
@@ -654,8 +720,44 @@ export function filtersToGroq(filters, selectedFilters = []) {
654
720
  return `(difficulty_string == "Novice" || difficulty_string == "Introductory" )`
655
721
  }
656
722
  return `difficulty_string == "${value}"`
657
- } else if (key === 'type' && !selectedFilters.includes(key)) {
723
+ } else if (key === 'tab' && !selectedFilters.includes(key)) {
724
+ if(value.toLowerCase() === Tabs.Individuals.name.toLowerCase()){
725
+ const conditions = individualLessonsTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
726
+ return ` (${conditions})`;
727
+ } else if(value.toLowerCase() === Tabs.Collections.name.toLowerCase()){
728
+ const conditions = collectionLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
729
+ return ` (${conditions})`;
730
+ } else if(value.toLowerCase() === Tabs.Tutorials.name.toLowerCase()){
731
+ const conditions = tutorialsLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
732
+ return ` (${conditions})`;
733
+ } else if(value.toLowerCase() === Tabs.Transcriptions.name.toLowerCase()){
734
+ const conditions = transcriptionsLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
735
+ return ` (${conditions})`;
736
+ } else if(value.toLowerCase() === Tabs.PlayAlongs.name.toLowerCase()){
737
+ const conditions = playAlongLessonTypes.map(lessonType => `_type == '${lessonType}'`).join(' || ');
738
+ return ` (${conditions})`;
739
+ } else if(value.toLowerCase() === Tabs.ExploreAll.name.toLowerCase()){
740
+ var allLessons = filterTypes[pageName] || [];
741
+ const conditions = allLessons.map(lessonType => `_type == '${lessonType}'`).join(' || ');
742
+ if (conditions === "") return '';
743
+ return ` (${conditions})`;
744
+ }else if(value.toLowerCase() === Tabs.RecentAll.name.toLowerCase()){
745
+ var allLessons = recentTypes[pageName] || [];
746
+ const conditions = allLessons.map(lessonType => `_type == '${lessonType}'`).join(' || ');
747
+ if (conditions === "") return '';
748
+ return ` (${conditions})`;
749
+ }
658
750
  return `_type == "${value}"`
751
+ } else if (key === 'type' && !selectedFilters.includes(key)) {
752
+ const typeKey = value.toLowerCase();
753
+ const lessonTypes = lessonTypesMapping[typeKey];
754
+ if (lessonTypes) {
755
+ const conditions = lessonTypes.map(
756
+ (lessonType) => `_type == '${lessonType}'`
757
+ ).join(' || ');
758
+ return ` (${conditions})`;
759
+ }
760
+ return `_type == "${value}"`;
659
761
  } else if (key === 'length_in_seconds') {
660
762
  if (value.includes('-')) {
661
763
  const [min, max] = value.split('-').map(Number)
@@ -666,6 +768,8 @@ export function filtersToGroq(filters, selectedFilters = []) {
666
768
  } else {
667
769
  return `${key} == ${value}`
668
770
  }
771
+ } else if (key === 'pageName') {
772
+ return ` `
669
773
  } else if (!selectedFilters.includes(key)) {
670
774
  return ` ${key} == ${/^\d+$/.test(value) ? value : `"$${value}"`}`
671
775
  }
@@ -1,4 +1,4 @@
1
- import { fetchUserPermissions } from './services/userPermissions.js'
1
+ import { fetchUserPermissions } from './services/user/permissions.js'
2
2
  import { plusMembershipPermissions } from './contentTypeConfig.js'
3
3
 
4
4
  export class FilterBuilder {
@@ -56,13 +56,13 @@ export class FilterBuilder {
56
56
  return filter
57
57
  }
58
58
 
59
- _getRoundedTime(){
59
+ _getRoundedTime() {
60
60
  // We need to set the published on filter date to be a round time so that it doesn't bypass the query cache
61
61
  // with every request by changing the filter date every second. I've set it to one minute past the current hour
62
62
  // because publishing usually publishes content on the hour exactly which means it should still skip the cache
63
63
  // when the new content is available.
64
- const now = new Date();
65
- return new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 1);
64
+ const now = new Date()
65
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), 1)
66
66
  }
67
67
 
68
68
  _applyContentStatuses() {
@@ -98,7 +98,7 @@ export class FilterBuilder {
98
98
  ) {
99
99
  // we must pull in future content here, otherwise we'll restrict on content this is published in the past and remove any scheduled content
100
100
  this.pullFutureContent = true
101
- const now = this._getRoundedTime().toISOString();
101
+ const now = this._getRoundedTime().toISOString()
102
102
  let statuses = [...this.availableContentStatuses]
103
103
  statuses.splice(statuses.indexOf(this.STATUS_SCHEDULED), 1)
104
104
  this._andWhere(
@@ -130,7 +130,7 @@ export class FilterBuilder {
130
130
 
131
131
  _applyPublishingDateRestrictions() {
132
132
  if (this.bypassPublishedDateRestriction) return this
133
- const now = this._getRoundedTime().toISOString();
133
+ const now = this._getRoundedTime().toISOString()
134
134
 
135
135
  if (this.getFutureContentOnly) {
136
136
  this._andWhere(`${this.prefix}published_on >= '${now}'`)
package/src/index.d.ts CHANGED
@@ -5,6 +5,16 @@ import {
5
5
  initializeService
6
6
  } from './services/config.js';
7
7
 
8
+ import {
9
+ getContentRows,
10
+ getLessonContentRows,
11
+ getNewAndUpcoming,
12
+ getRecent,
13
+ getRecommendedForYou,
14
+ getScheduleContentRows,
15
+ getTabResults
16
+ } from './services/content.js';
17
+
8
18
  import {
9
19
  isContentLiked,
10
20
  likeContent,
@@ -32,9 +42,8 @@ import {
32
42
  } from './services/dataContext.js';
33
43
 
34
44
  import {
35
- setLastUpdatedTime,
36
- wasLastUpdateOlderThanXSeconds
37
- } from './services/lastUpdated.js';
45
+ getActiveDiscussions
46
+ } from './services/forum.js';
38
47
 
39
48
  import {
40
49
  addItemToPlaylist,
@@ -110,6 +119,7 @@ import {
110
119
  import {
111
120
  rankCategories,
112
121
  rankItems,
122
+ recommendations,
113
123
  similarItems
114
124
  } from './services/recommendations.js';
115
125
 
@@ -143,14 +153,17 @@ import {
143
153
  fetchPackData,
144
154
  fetchParentForDownload,
145
155
  fetchPlayAlongsCount,
156
+ fetchRecent,
146
157
  fetchRelatedLessons,
147
158
  fetchRelatedSongs,
148
159
  fetchReturning,
149
160
  fetchSanity,
161
+ fetchScheduledAndNewReleases,
150
162
  fetchScheduledReleases,
151
163
  fetchShowsData,
152
164
  fetchSongArtistCount,
153
165
  fetchSongById,
166
+ fetchTabData,
154
167
  fetchTopLevelParentId,
155
168
  fetchUpcomingEvents,
156
169
  getSortOrder,
@@ -160,7 +173,16 @@ import {
160
173
  import {
161
174
  fetchUserPermissions,
162
175
  reset
163
- } from './services/userPermissions.js';
176
+ } from './services/user/permissions.js';
177
+
178
+ import {
179
+ login,
180
+ logout
181
+ } from './services/user/sessions.js';
182
+
183
+ import {
184
+ getUserActivityStats
185
+ } from './services/userActivity.js';
164
186
 
165
187
  declare module 'musora-content-services' {
166
188
  export {
@@ -230,15 +252,18 @@ declare module 'musora-content-services' {
230
252
  fetchPlaylist,
231
253
  fetchPlaylistItem,
232
254
  fetchPlaylistItems,
255
+ fetchRecent,
233
256
  fetchRelatedLessons,
234
257
  fetchRelatedSongs,
235
258
  fetchReturning,
236
259
  fetchSanity,
260
+ fetchScheduledAndNewReleases,
237
261
  fetchScheduledReleases,
238
262
  fetchShowsData,
239
263
  fetchSongArtistCount,
240
264
  fetchSongById,
241
265
  fetchSongsInProgress,
266
+ fetchTabData,
242
267
  fetchTopComment,
243
268
  fetchTopLevelParentId,
244
269
  fetchUpcomingEvents,
@@ -249,15 +274,24 @@ declare module 'musora-content-services' {
249
274
  fetchUserPermissions,
250
275
  fetchUserPermissionsData,
251
276
  fetchUserPlaylists,
277
+ getActiveDiscussions,
252
278
  getAllCompleted,
253
279
  getAllStarted,
254
280
  getAllStartedOrCompleted,
281
+ getContentRows,
282
+ getLessonContentRows,
283
+ getNewAndUpcoming,
255
284
  getProgressPercentage,
256
285
  getProgressPercentageByIds,
257
286
  getProgressState,
258
287
  getProgressStateByIds,
288
+ getRecent,
289
+ getRecommendedForYou,
259
290
  getResumeTimeSeconds,
291
+ getScheduleContentRows,
260
292
  getSortOrder,
293
+ getTabResults,
294
+ getUserActivityStats,
261
295
  globalConfig,
262
296
  initializeService,
263
297
  isContentLiked,
@@ -265,6 +299,8 @@ declare module 'musora-content-services' {
265
299
  likeComment,
266
300
  likeContent,
267
301
  likePlaylist,
302
+ login,
303
+ logout,
268
304
  openComment,
269
305
  pinPlaylist,
270
306
  playback,
@@ -284,11 +320,11 @@ declare module 'musora-content-services' {
284
320
  postRecordWatchSession,
285
321
  rankCategories,
286
322
  rankItems,
323
+ recommendations,
287
324
  recordWatchSession,
288
325
  replyToComment,
289
326
  reportPlaylist,
290
327
  reset,
291
- setLastUpdatedTime,
292
328
  setStudentViewForUser,
293
329
  similarItems,
294
330
  unassignModeratorToComment,
@@ -298,6 +334,5 @@ declare module 'musora-content-services' {
298
334
  updatePlaylist,
299
335
  updatePlaylistItem,
300
336
  verifyLocalDataContext,
301
- wasLastUpdateOlderThanXSeconds,
302
337
  }
303
338
  }
package/src/index.js CHANGED
@@ -5,6 +5,16 @@ import {
5
5
  initializeService
6
6
  } from './services/config.js';
7
7
 
8
+ import {
9
+ getContentRows,
10
+ getLessonContentRows,
11
+ getNewAndUpcoming,
12
+ getRecent,
13
+ getRecommendedForYou,
14
+ getScheduleContentRows,
15
+ getTabResults
16
+ } from './services/content.js';
17
+
8
18
  import {
9
19
  isContentLiked,
10
20
  likeContent,
@@ -32,9 +42,8 @@ import {
32
42
  } from './services/dataContext.js';
33
43
 
34
44
  import {
35
- setLastUpdatedTime,
36
- wasLastUpdateOlderThanXSeconds
37
- } from './services/lastUpdated.js';
45
+ getActiveDiscussions
46
+ } from './services/forum.js';
38
47
 
39
48
  import {
40
49
  addItemToPlaylist,
@@ -110,6 +119,7 @@ import {
110
119
  import {
111
120
  rankCategories,
112
121
  rankItems,
122
+ recommendations,
113
123
  similarItems
114
124
  } from './services/recommendations.js';
115
125
 
@@ -143,14 +153,17 @@ import {
143
153
  fetchPackData,
144
154
  fetchParentForDownload,
145
155
  fetchPlayAlongsCount,
156
+ fetchRecent,
146
157
  fetchRelatedLessons,
147
158
  fetchRelatedSongs,
148
159
  fetchReturning,
149
160
  fetchSanity,
161
+ fetchScheduledAndNewReleases,
150
162
  fetchScheduledReleases,
151
163
  fetchShowsData,
152
164
  fetchSongArtistCount,
153
165
  fetchSongById,
166
+ fetchTabData,
154
167
  fetchTopLevelParentId,
155
168
  fetchUpcomingEvents,
156
169
  getSortOrder,
@@ -160,7 +173,16 @@ import {
160
173
  import {
161
174
  fetchUserPermissions,
162
175
  reset
163
- } from './services/userPermissions.js';
176
+ } from './services/user/permissions.js';
177
+
178
+ import {
179
+ login,
180
+ logout
181
+ } from './services/user/sessions.js';
182
+
183
+ import {
184
+ getUserActivityStats
185
+ } from './services/userActivity.js';
164
186
 
165
187
  export {
166
188
  addItemToPlaylist,
@@ -229,15 +251,18 @@ export {
229
251
  fetchPlaylist,
230
252
  fetchPlaylistItem,
231
253
  fetchPlaylistItems,
254
+ fetchRecent,
232
255
  fetchRelatedLessons,
233
256
  fetchRelatedSongs,
234
257
  fetchReturning,
235
258
  fetchSanity,
259
+ fetchScheduledAndNewReleases,
236
260
  fetchScheduledReleases,
237
261
  fetchShowsData,
238
262
  fetchSongArtistCount,
239
263
  fetchSongById,
240
264
  fetchSongsInProgress,
265
+ fetchTabData,
241
266
  fetchTopComment,
242
267
  fetchTopLevelParentId,
243
268
  fetchUpcomingEvents,
@@ -248,15 +273,24 @@ export {
248
273
  fetchUserPermissions,
249
274
  fetchUserPermissionsData,
250
275
  fetchUserPlaylists,
276
+ getActiveDiscussions,
251
277
  getAllCompleted,
252
278
  getAllStarted,
253
279
  getAllStartedOrCompleted,
280
+ getContentRows,
281
+ getLessonContentRows,
282
+ getNewAndUpcoming,
254
283
  getProgressPercentage,
255
284
  getProgressPercentageByIds,
256
285
  getProgressState,
257
286
  getProgressStateByIds,
287
+ getRecent,
288
+ getRecommendedForYou,
258
289
  getResumeTimeSeconds,
290
+ getScheduleContentRows,
259
291
  getSortOrder,
292
+ getTabResults,
293
+ getUserActivityStats,
260
294
  globalConfig,
261
295
  initializeService,
262
296
  isContentLiked,
@@ -264,6 +298,8 @@ export {
264
298
  likeComment,
265
299
  likeContent,
266
300
  likePlaylist,
301
+ login,
302
+ logout,
267
303
  openComment,
268
304
  pinPlaylist,
269
305
  playback,
@@ -283,11 +319,11 @@ export {
283
319
  postRecordWatchSession,
284
320
  rankCategories,
285
321
  rankItems,
322
+ recommendations,
286
323
  recordWatchSession,
287
324
  replyToComment,
288
325
  reportPlaylist,
289
326
  reset,
290
- setLastUpdatedTime,
291
327
  setStudentViewForUser,
292
328
  similarItems,
293
329
  unassignModeratorToComment,
@@ -297,5 +333,4 @@ export {
297
333
  updatePlaylist,
298
334
  updatePlaylistItem,
299
335
  verifyLocalDataContext,
300
- wasLastUpdateOlderThanXSeconds,
301
336
  };
@@ -1,4 +1,4 @@
1
- import { globalConfig } from './config.js'
1
+ import { globalConfig } from '../services/config'
2
2
 
3
3
  /**
4
4
  * Exported functions that are excluded from index generation.
@@ -6,6 +6,15 @@ import { globalConfig } from './config.js'
6
6
  * @type {string[]}
7
7
  */
8
8
  const excludeFromGeneratedIndex = ['wasLastUpdateOlderThanXSeconds', 'setLastUpdatedTime']
9
+
10
+ /**
11
+ * Checks if the last update was older than X seconds.
12
+ *
13
+ * @param {number} seconds - The number of seconds to compare.
14
+ * @param {string} key - The key to check the last updated time.
15
+ *
16
+ * @returns {boolean} - True if the last update was older than X seconds, false otherwise.
17
+ */
9
18
  export function wasLastUpdateOlderThanXSeconds(seconds, key) {
10
19
  let lastUpdated = globalConfig.localStorage.getItem(key)
11
20
  if (!lastUpdated) return false
@@ -13,6 +22,13 @@ export function wasLastUpdateOlderThanXSeconds(seconds, key) {
13
22
  return new Date().getTime() - lastUpdated > verifyServerTime
14
23
  }
15
24
 
25
+ /**
26
+ * Sets the last updated time.
27
+ *
28
+ * @param {string} key - The key to set the last updated time.
29
+ *
30
+ * @returns {void}
31
+ */
16
32
  export function setLastUpdatedTime(key) {
17
33
  globalConfig.localStorage.setItem(key, new Date().getTime()?.toString())
18
34
  }
File without changes