musora-content-services 2.3.2 → 2.3.3
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.
- package/.editorconfig +0 -0
- package/.github/workflows/node.js.yml +0 -0
- package/.prettierignore +0 -0
- package/.prettierrc +0 -0
- package/CHANGELOG.md +2 -0
- package/README.md +0 -0
- package/babel.config.cjs +0 -0
- package/docs/Content-Organization.html +0 -0
- package/docs/Gamification.html +0 -0
- package/docs/Playlists.html +0 -0
- package/docs/api_types.js.html +0 -0
- package/docs/config.js.html +0 -0
- package/docs/content-org_playlists-types.js.html +0 -0
- package/docs/content-org_playlists.js.html +0 -0
- package/docs/content-org_types.js.html +0 -0
- package/docs/content.js.html +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/gamification_awards.js.html +0 -0
- package/docs/gamification_gamification.js.html +0 -0
- package/docs/gamification_types.js.html +0 -0
- package/docs/global.html +0 -0
- package/docs/index.html +0 -0
- package/docs/module-Awards.html +0 -0
- package/docs/module-Config.html +0 -0
- package/docs/module-Content-Organization-Playlists.html +0 -0
- package/docs/module-Content-Organization.html +0 -0
- package/docs/module-Content-Services-V2.html +0 -0
- package/docs/module-Playlists.html +0 -0
- package/docs/module-Railcontent-Services.html +0 -0
- package/docs/module-Sanity-Services.html +0 -0
- package/docs/module-Session-Management.html +0 -0
- package/docs/module-User-Permissions.html +0 -0
- package/docs/module-playlists.html +0 -0
- package/docs/module-playlists_.html +0 -0
- package/docs/railcontent.js.html +0 -0
- package/docs/sanity.js.html +0 -0
- package/docs/scripts/collapse.js +0 -0
- package/docs/scripts/commonNav.js +0 -0
- package/docs/scripts/linenumber.js +0 -0
- package/docs/scripts/nav.js +0 -0
- package/docs/scripts/polyfill.js +0 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +0 -0
- package/docs/scripts/prettify/lang-css.js +0 -0
- package/docs/scripts/prettify/prettify.js +0 -0
- package/docs/scripts/search.js +0 -0
- package/docs/styles/jsdoc.css +0 -0
- package/docs/styles/prettify.css +0 -0
- package/docs/user_permissions.js.html +0 -0
- package/docs/user_sessions.js.html +0 -0
- package/docs/user_types.js.html +0 -0
- package/jest.config.js +0 -0
- package/jsdoc.json +0 -0
- package/package.json +1 -1
- package/src/contentMetaData.js +0 -0
- package/src/filterBuilder.js +0 -0
- package/src/index.d.ts +18 -0
- package/src/index.js +18 -0
- package/src/lib/httpHelper.js +0 -0
- package/src/lib/lastUpdated.js +0 -0
- package/src/services/api/types.js +0 -0
- package/src/services/config.js +0 -0
- package/src/services/content-org/playlists-types.js +0 -0
- package/src/services/content-org/playlists.js +0 -0
- package/src/services/contentLikes.js +0 -0
- package/src/services/contentProgress.js +0 -0
- package/src/services/dataContext.js +0 -0
- package/src/services/forum.js +0 -0
- package/src/services/gamification/awards.js +0 -0
- package/src/services/gamification/gamification.js +0 -0
- package/src/services/gamification/types.js +0 -0
- package/src/services/imageSRCBuilder.js +139 -0
- package/src/services/imageSRCVerify.js +114 -0
- package/src/services/railcontent.js +3 -3
- package/src/services/recommendations.js +0 -0
- package/src/services/user/management.js +0 -0
- package/src/services/user/permissions.js +0 -0
- package/src/services/user/sessions.js +0 -0
- package/src/services/user/types.js +0 -0
- package/test/content.test.js +0 -0
- package/test/contentLikes.test.js +0 -0
- package/test/contentProgress.test.js +0 -0
- package/test/dataContext.test.js +0 -0
- package/test/forum.test.js +0 -0
- package/test/imageSRCBuilder.test.js +37 -0
- package/test/imageSRCVerify.test.js +160 -0
- package/test/initializeTests.js +0 -0
- package/test/lib/lastUpdated.test.js +0 -0
- package/test/live/contentProgressLive.test.js +0 -0
- package/test/live/railcontentLive.test.js +0 -0
- package/test/localStorageMock.js +0 -0
- package/test/log.js +0 -0
- package/test/mockData/mockData_fetchByRailContentIds_one_content.json +0 -0
- package/test/sanityQueryService.test.js +0 -0
- package/test/user/permissions.test.js +0 -0
- package/test/userActivity.test.js +0 -0
- package/tools/generate-index.cjs +0 -0
- package/.yarnrc.yml +0 -1
- package/docs/module-Content-Services.html +0 -763
package/.editorconfig
CHANGED
|
File without changes
|
|
File without changes
|
package/.prettierignore
CHANGED
|
File without changes
|
package/.prettierrc
CHANGED
|
File without changes
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.3.3](https://github.com/railroadmedia/musora-content-services/compare/v2.3.2...v2.3.3) (2025-04-02)
|
|
6
|
+
|
|
5
7
|
### [2.3.2](https://github.com/railroadmedia/musora-content-services/compare/v2.3.1...v2.3.2) (2025-03-31)
|
|
6
8
|
|
|
7
9
|
### [2.3.1](https://github.com/railroadmedia/musora-content-services/compare/v2.3.0...v2.3.1) (2025-03-31)
|
package/README.md
CHANGED
|
File without changes
|
package/babel.config.cjs
CHANGED
|
File without changes
|
|
File without changes
|
package/docs/Gamification.html
CHANGED
|
File without changes
|
package/docs/Playlists.html
CHANGED
|
File without changes
|
package/docs/api_types.js.html
CHANGED
|
File without changes
|
package/docs/config.js.html
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/content.js.html
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/global.html
CHANGED
|
File without changes
|
package/docs/index.html
CHANGED
|
File without changes
|
package/docs/module-Awards.html
CHANGED
|
File without changes
|
package/docs/module-Config.html
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/railcontent.js.html
CHANGED
|
File without changes
|
package/docs/sanity.js.html
CHANGED
|
File without changes
|
package/docs/scripts/collapse.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/scripts/nav.js
CHANGED
|
File without changes
|
package/docs/scripts/polyfill.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/scripts/search.js
CHANGED
|
File without changes
|
package/docs/styles/jsdoc.css
CHANGED
|
File without changes
|
package/docs/styles/prettify.css
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/docs/user_types.js.html
CHANGED
|
File without changes
|
package/jest.config.js
CHANGED
|
File without changes
|
package/jsdoc.json
CHANGED
|
File without changes
|
package/package.json
CHANGED
package/src/contentMetaData.js
CHANGED
|
File without changes
|
package/src/filterBuilder.js
CHANGED
|
File without changes
|
package/src/index.d.ts
CHANGED
|
@@ -55,6 +55,18 @@ import {
|
|
|
55
55
|
fetchAwardsForUser
|
|
56
56
|
} from './services/gamification/awards.js';
|
|
57
57
|
|
|
58
|
+
import {
|
|
59
|
+
applyCloudflareWrapper,
|
|
60
|
+
applySanityTransformations,
|
|
61
|
+
buildImageSRC
|
|
62
|
+
} from './services/imageSRCBuilder.js';
|
|
63
|
+
|
|
64
|
+
import {
|
|
65
|
+
extractSanityUrl,
|
|
66
|
+
isBucketUrl,
|
|
67
|
+
verifyImageSRC
|
|
68
|
+
} from './services/imageSRCVerify.js';
|
|
69
|
+
|
|
58
70
|
import {
|
|
59
71
|
assignModeratorToComment,
|
|
60
72
|
closeComment,
|
|
@@ -214,10 +226,13 @@ import {
|
|
|
214
226
|
declare module 'musora-content-services' {
|
|
215
227
|
export {
|
|
216
228
|
addItemToPlaylist,
|
|
229
|
+
applyCloudflareWrapper,
|
|
230
|
+
applySanityTransformations,
|
|
217
231
|
assignModeratorToComment,
|
|
218
232
|
assignmentStatusCompleted,
|
|
219
233
|
assignmentStatusReset,
|
|
220
234
|
blockUser,
|
|
235
|
+
buildImageSRC,
|
|
221
236
|
closeComment,
|
|
222
237
|
contentStatusCompleted,
|
|
223
238
|
contentStatusReset,
|
|
@@ -231,6 +246,7 @@ declare module 'musora-content-services' {
|
|
|
231
246
|
deletePracticeSession,
|
|
232
247
|
duplicatePlaylist,
|
|
233
248
|
editComment,
|
|
249
|
+
extractSanityUrl,
|
|
234
250
|
fetchAll,
|
|
235
251
|
fetchAllCompletedStates,
|
|
236
252
|
fetchAllFilterOptions,
|
|
@@ -334,6 +350,7 @@ declare module 'musora-content-services' {
|
|
|
334
350
|
getUserWeeklyStats,
|
|
335
351
|
globalConfig,
|
|
336
352
|
initializeService,
|
|
353
|
+
isBucketUrl,
|
|
337
354
|
isContentLiked,
|
|
338
355
|
jumpToContinueContent,
|
|
339
356
|
likeComment,
|
|
@@ -378,6 +395,7 @@ declare module 'musora-content-services' {
|
|
|
378
395
|
updatePlaylist,
|
|
379
396
|
updatePlaylistItem,
|
|
380
397
|
updateUserPractice,
|
|
398
|
+
verifyImageSRC,
|
|
381
399
|
verifyLocalDataContext,
|
|
382
400
|
}
|
|
383
401
|
}
|
package/src/index.js
CHANGED
|
@@ -55,6 +55,18 @@ import {
|
|
|
55
55
|
fetchAwardsForUser
|
|
56
56
|
} from './services/gamification/awards.js';
|
|
57
57
|
|
|
58
|
+
import {
|
|
59
|
+
applyCloudflareWrapper,
|
|
60
|
+
applySanityTransformations,
|
|
61
|
+
buildImageSRC
|
|
62
|
+
} from './services/imageSRCBuilder.js';
|
|
63
|
+
|
|
64
|
+
import {
|
|
65
|
+
extractSanityUrl,
|
|
66
|
+
isBucketUrl,
|
|
67
|
+
verifyImageSRC
|
|
68
|
+
} from './services/imageSRCVerify.js';
|
|
69
|
+
|
|
58
70
|
import {
|
|
59
71
|
assignModeratorToComment,
|
|
60
72
|
closeComment,
|
|
@@ -213,10 +225,13 @@ import {
|
|
|
213
225
|
|
|
214
226
|
export {
|
|
215
227
|
addItemToPlaylist,
|
|
228
|
+
applyCloudflareWrapper,
|
|
229
|
+
applySanityTransformations,
|
|
216
230
|
assignModeratorToComment,
|
|
217
231
|
assignmentStatusCompleted,
|
|
218
232
|
assignmentStatusReset,
|
|
219
233
|
blockUser,
|
|
234
|
+
buildImageSRC,
|
|
220
235
|
closeComment,
|
|
221
236
|
contentStatusCompleted,
|
|
222
237
|
contentStatusReset,
|
|
@@ -230,6 +245,7 @@ export {
|
|
|
230
245
|
deletePracticeSession,
|
|
231
246
|
duplicatePlaylist,
|
|
232
247
|
editComment,
|
|
248
|
+
extractSanityUrl,
|
|
233
249
|
fetchAll,
|
|
234
250
|
fetchAllCompletedStates,
|
|
235
251
|
fetchAllFilterOptions,
|
|
@@ -333,6 +349,7 @@ export {
|
|
|
333
349
|
getUserWeeklyStats,
|
|
334
350
|
globalConfig,
|
|
335
351
|
initializeService,
|
|
352
|
+
isBucketUrl,
|
|
336
353
|
isContentLiked,
|
|
337
354
|
jumpToContinueContent,
|
|
338
355
|
likeComment,
|
|
@@ -377,5 +394,6 @@ export {
|
|
|
377
394
|
updatePlaylist,
|
|
378
395
|
updatePlaylistItem,
|
|
379
396
|
updateUserPractice,
|
|
397
|
+
verifyImageSRC,
|
|
380
398
|
verifyLocalDataContext,
|
|
381
399
|
};
|
package/src/lib/httpHelper.js
CHANGED
|
File without changes
|
package/src/lib/lastUpdated.js
CHANGED
|
File without changes
|
|
File without changes
|
package/src/services/config.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/services/forum.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds an optimized image URL using both Sanity and Cloudflare Image Resizing services
|
|
3
|
+
*
|
|
4
|
+
* This function takes a Sanity CDN URL and image transformation parameters, then:
|
|
5
|
+
* 1. Adds appropriate transformation parameters to the Sanity URL
|
|
6
|
+
* 2. Wraps the resulting URL with Cloudflare's Image Resizing service
|
|
7
|
+
* 3. Maps compatible parameters between the two services for optimal results
|
|
8
|
+
*
|
|
9
|
+
* @param {string} url - The original image URL, typically from Sanity CDN
|
|
10
|
+
* @param {Object} options - Image transformation options
|
|
11
|
+
* @param {number} [options.width] - Desired image width in pixels
|
|
12
|
+
* @param {number} [options.height] - Desired image height in pixels
|
|
13
|
+
* @param {number} [options.quality] - Image quality (1-100)
|
|
14
|
+
* @param {string} [options.fit] - Resize strategy: 'cover', 'contain', 'scale-down', 'none'
|
|
15
|
+
* @param {string} [options.gravity] - Content positioning: 'auto', 'top', 'bottom', 'left', 'right', etc.
|
|
16
|
+
* @param {string} [options.crop] - Sanity-specific crop mode
|
|
17
|
+
* @param {string} [options.format] - Image format: 'auto', 'webp', 'jpeg', 'png', etc.
|
|
18
|
+
* @param {number} [options.blur] - Blur amount
|
|
19
|
+
* @param {number} [options.sharpen] - Sharpen amount
|
|
20
|
+
* @param {number} [options.saturation] - Saturation adjustment
|
|
21
|
+
* @param {number} [options.brightness] - Brightness adjustment
|
|
22
|
+
* @param {number} [options.contrast] - Contrast adjustment
|
|
23
|
+
* @param {number} [options.gamma] - Gamma adjustment
|
|
24
|
+
* @param {number} [options.rotate] - Rotation angle in degrees
|
|
25
|
+
* @param {number} [options.dpr] - Device pixel ratio for responsive images
|
|
26
|
+
* @param {string} [options.background] - Background color (e.g., '#FFFFFF')
|
|
27
|
+
* @param {number} [options.padding] - Padding to add around the image
|
|
28
|
+
* @param {boolean} [options.anim] - Whether to preserve animation in GIFs
|
|
29
|
+
* @param {string} [options.onerror] - Error handling strategy
|
|
30
|
+
* @param {string} [options.compression] - Compression strategy
|
|
31
|
+
* @param {string} [options.fetchFormat] - Format to request from origin
|
|
32
|
+
* @param {string} [options.sampling] - Chroma subsampling strategy
|
|
33
|
+
* @param {string} [options.metadata] - Metadata to preserve
|
|
34
|
+
*
|
|
35
|
+
* @returns {string} The fully constructed image URL with transformations
|
|
36
|
+
*/
|
|
37
|
+
export function buildImageSRC(url, options = {}) {
|
|
38
|
+
// Process Sanity URL first if applicable
|
|
39
|
+
if (url.includes('cdn.sanity.io')) {
|
|
40
|
+
url = applySanityTransformations(url, options)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Then apply Cloudflare transformations
|
|
44
|
+
return applyCloudflareWrapper(url, options)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Applies Sanity-specific image transformations to a Sanity CDN URL
|
|
49
|
+
*
|
|
50
|
+
* @param {string} url - The Sanity CDN URL
|
|
51
|
+
* @param {Object} options - Image transformation options
|
|
52
|
+
* @returns {string} URL with Sanity transformations applied
|
|
53
|
+
* @private
|
|
54
|
+
*/
|
|
55
|
+
export function applySanityTransformations(url, options) {
|
|
56
|
+
const { width, height, quality } = options
|
|
57
|
+
|
|
58
|
+
const sanityOptions = []
|
|
59
|
+
|
|
60
|
+
// Dimensions
|
|
61
|
+
if (width) sanityOptions.push(`w=${width}`)
|
|
62
|
+
if (height) sanityOptions.push(`h=${height}`)
|
|
63
|
+
if (quality) sanityOptions.push(`q=${quality}`)
|
|
64
|
+
|
|
65
|
+
// Add parameters to Sanity URL
|
|
66
|
+
const sanityQuery = sanityOptions.length > 0 ? `?${sanityOptions.join('&')}` : ''
|
|
67
|
+
return `${url}${sanityQuery}`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Wraps a URL with Cloudflare's Image Resizing service and applies transformations
|
|
72
|
+
*
|
|
73
|
+
* @param {string} url - The source URL (can be any image URL)
|
|
74
|
+
* @param {Object} options - Image transformation options
|
|
75
|
+
* @returns {string} URL with Cloudflare transformations applied
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
export function applyCloudflareWrapper(url, options) {
|
|
79
|
+
const {
|
|
80
|
+
width,
|
|
81
|
+
height,
|
|
82
|
+
quality,
|
|
83
|
+
fit,
|
|
84
|
+
gravity,
|
|
85
|
+
format,
|
|
86
|
+
blur,
|
|
87
|
+
sharpen,
|
|
88
|
+
brightness,
|
|
89
|
+
contrast,
|
|
90
|
+
gamma,
|
|
91
|
+
rotate,
|
|
92
|
+
dpr,
|
|
93
|
+
background,
|
|
94
|
+
padding,
|
|
95
|
+
anim,
|
|
96
|
+
onerror,
|
|
97
|
+
compression,
|
|
98
|
+
fetchFormat,
|
|
99
|
+
sampling,
|
|
100
|
+
metadata,
|
|
101
|
+
} = options
|
|
102
|
+
|
|
103
|
+
const cloudflareOptions = []
|
|
104
|
+
|
|
105
|
+
// Build Cloudflare options - required parameters
|
|
106
|
+
if (width) cloudflareOptions.push(`width=${width}`)
|
|
107
|
+
if (height) cloudflareOptions.push(`height=${height}`)
|
|
108
|
+
if (quality) cloudflareOptions.push(`quality=${quality}`)
|
|
109
|
+
|
|
110
|
+
// Add optional Cloudflare parameters
|
|
111
|
+
if (format) cloudflareOptions.push(`format=${format}`)
|
|
112
|
+
if (fit) cloudflareOptions.push(`fit=${fit}`)
|
|
113
|
+
if (gravity) cloudflareOptions.push(`gravity=${gravity}`)
|
|
114
|
+
|
|
115
|
+
if (sharpen !== null && sharpen !== undefined) cloudflareOptions.push(`sharpen=${sharpen}`)
|
|
116
|
+
if (blur !== null && blur !== undefined) cloudflareOptions.push(`blur=${blur}`)
|
|
117
|
+
if (brightness !== null && brightness !== undefined)
|
|
118
|
+
cloudflareOptions.push(`brightness=${brightness}`)
|
|
119
|
+
if (contrast !== null && contrast !== undefined) cloudflareOptions.push(`contrast=${contrast}`)
|
|
120
|
+
if (gamma !== null && gamma !== undefined) cloudflareOptions.push(`gamma=${gamma}`)
|
|
121
|
+
if (rotate !== null && rotate !== undefined) cloudflareOptions.push(`rotate=${rotate}`)
|
|
122
|
+
if (dpr !== null && dpr !== undefined) cloudflareOptions.push(`dpr=${dpr}`)
|
|
123
|
+
|
|
124
|
+
if (metadata !== null && metadata !== undefined) cloudflareOptions.push(`metadata=${metadata}`)
|
|
125
|
+
if (onerror !== null && onerror !== undefined) cloudflareOptions.push(`onerror=${onerror}`)
|
|
126
|
+
if (anim === false) cloudflareOptions.push('anim=false')
|
|
127
|
+
if (background !== null && background !== undefined)
|
|
128
|
+
cloudflareOptions.push(`background=${background}`)
|
|
129
|
+
if (fetchFormat !== null && fetchFormat !== undefined)
|
|
130
|
+
cloudflareOptions.push(`fetchFormat=${fetchFormat}`)
|
|
131
|
+
if (compression !== null && compression !== undefined)
|
|
132
|
+
cloudflareOptions.push(`compression=${compression}`)
|
|
133
|
+
if (sampling !== null && sampling !== undefined) cloudflareOptions.push(`sampling=${sampling}`)
|
|
134
|
+
if (padding !== null && padding !== undefined) cloudflareOptions.push(`padding=${padding}`)
|
|
135
|
+
|
|
136
|
+
const optionsString = cloudflareOptions.length > 0 ? cloudflareOptions.join(',') : ''
|
|
137
|
+
|
|
138
|
+
return `https://www.musora.com/cdn-cgi/image/${optionsString}/${url}`
|
|
139
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies if an image URL follows best practices for optimization
|
|
3
|
+
*
|
|
4
|
+
* This function checks whether:
|
|
5
|
+
* 1. Sanity CDN images include query parameters for optimization
|
|
6
|
+
* 2. Direct S3 images are avoided (should use CDN instead)
|
|
7
|
+
*
|
|
8
|
+
* @param {string} src - The image source URL to verify
|
|
9
|
+
* @returns {void}
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Check a direct Sanity URL
|
|
13
|
+
* verifyImageSRC('https://cdn.sanity.io/images/4032r8py/staging/504c4e3393170f937a579de6f3c75c457b0c9e65-640x360.jpg');
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Check a Sanity URL inside a Cloudflare URL
|
|
17
|
+
* verifyImageSRC('https://www.musora.com/cdn-cgi/image/width=500,quality=95/https://cdn.sanity.io/images/4032r8py/staging/504c4e3393170f937a579de6f3c75c457b0c9e65-640x360.jpg');
|
|
18
|
+
*/
|
|
19
|
+
export function verifyImageSRC(src) {
|
|
20
|
+
// Exit early if the URL is empty
|
|
21
|
+
if (!src) return
|
|
22
|
+
|
|
23
|
+
// Check for S3 direct URLs
|
|
24
|
+
if (isBucketUrl(src)) {
|
|
25
|
+
warnAboutDirectS3Url(src)
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check for Sanity URLs
|
|
30
|
+
if (src.includes('cdn.sanity.io')) {
|
|
31
|
+
verifySanityUrl(src)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Checks if a URL is a direct link to an S3 bucket
|
|
37
|
+
*
|
|
38
|
+
* @param {string} url - The URL to check
|
|
39
|
+
* @returns {boolean} True if the URL is a direct S3 bucket URL
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
export function isBucketUrl(url) {
|
|
43
|
+
// Check for common S3 patterns
|
|
44
|
+
return (
|
|
45
|
+
url.includes('.s3.amazonaws.com') ||
|
|
46
|
+
url.includes('s3.us-') ||
|
|
47
|
+
url.includes('amazonaws.com/') ||
|
|
48
|
+
(url.includes('musora-') && url.includes('.s3.'))
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Issues a warning about using direct S3 URLs instead of a CDN
|
|
54
|
+
*
|
|
55
|
+
* @param {string} url - The S3 URL that triggered the warning
|
|
56
|
+
* @private
|
|
57
|
+
*/
|
|
58
|
+
function warnAboutDirectS3Url(url) {
|
|
59
|
+
// Only warn in development mode
|
|
60
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
61
|
+
console.warn(`WARNING: Direct S3 bucket URL detected: ${url}
|
|
62
|
+
This is not recommended. Use Cloudfront or another CDN for better performance.`)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Extracts a Sanity URL from a potentially Cloudflare-wrapped URL
|
|
68
|
+
*
|
|
69
|
+
* @param {string} url - The URL to process
|
|
70
|
+
* @returns {string} The extracted Sanity URL
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
export function extractSanityUrl(url) {
|
|
74
|
+
// If this is a Cloudflare URL, extract the Sanity portion
|
|
75
|
+
if (url.includes('/cdn-cgi/image/')) {
|
|
76
|
+
// Split the URL to get the portion after /cdn-cgi/image/[parameters]/
|
|
77
|
+
const parts = url.split('/cdn-cgi/image/')
|
|
78
|
+
if (parts.length > 1) {
|
|
79
|
+
// Get everything after the first / that follows the Cloudflare parameters
|
|
80
|
+
const cfParamsAndSanityUrl = parts[1]
|
|
81
|
+
const slashIndex = cfParamsAndSanityUrl.indexOf('/', 0)
|
|
82
|
+
if (slashIndex !== -1) {
|
|
83
|
+
let sanityUrl = cfParamsAndSanityUrl.substring(slashIndex + 1)
|
|
84
|
+
return sanityUrl
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If not a Cloudflare URL or extraction failed, return the original URL
|
|
90
|
+
return url
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Verifies if a Sanity CDN image URL includes optimization parameters
|
|
95
|
+
*
|
|
96
|
+
* @param {string} src - The Sanity image URL to verify
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
function verifySanityUrl(src) {
|
|
100
|
+
// Extract the Sanity URL if it's wrapped in a Cloudflare URL
|
|
101
|
+
const sanityUrl = extractSanityUrl(src)
|
|
102
|
+
|
|
103
|
+
// Check if the Sanity URL has parameters (any query string)
|
|
104
|
+
const hasParameters = sanityUrl.includes('?')
|
|
105
|
+
|
|
106
|
+
// Warn if no parameters are found
|
|
107
|
+
if (!hasParameters) {
|
|
108
|
+
// Only warn in development mode
|
|
109
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
110
|
+
console.warn(`WARNING: Sanity CDN URL without parameters detected: ${src}
|
|
111
|
+
This may cause performance issues. Consider adding image transformations using the buildImageSRC MCS service.`)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -222,7 +222,7 @@ export async function fetchCompletedContent(type = 'all', brand, { page, limit }
|
|
|
222
222
|
* .catch(error => console.error(error));
|
|
223
223
|
*/
|
|
224
224
|
export async function fetchContentPageUserData(contentId) {
|
|
225
|
-
let url = `/content/${contentId}/user_data/${globalConfig.railcontentConfig.userId}`
|
|
225
|
+
let url = `/api/content/v1/${contentId}/user_data/${globalConfig.railcontentConfig.userId}`
|
|
226
226
|
const headers = {
|
|
227
227
|
'Content-Type': 'application/json',
|
|
228
228
|
Accept: 'application/json',
|
|
@@ -873,8 +873,8 @@ export async function postContentComplete(contentId) {
|
|
|
873
873
|
}
|
|
874
874
|
|
|
875
875
|
export async function postContentReset(contentId) {
|
|
876
|
-
let url = `/content/user/progress/reset`
|
|
877
|
-
return postDataHandler(url
|
|
876
|
+
let url = `/api/content/v1/user/progress/reset/${contentId}`
|
|
877
|
+
return postDataHandler(url)
|
|
878
878
|
}
|
|
879
879
|
|
|
880
880
|
/**
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/test/content.test.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/test/dataContext.test.js
CHANGED
|
File without changes
|
package/test/forum.test.js
CHANGED
|
File without changes
|