musora-content-services 2.102.1 → 2.102.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.
- package/CHANGELOG.md +7 -0
- package/package.json +3 -2
- package/src/lib/sanity/filter.ts +460 -0
- package/src/lib/sanity/query.ts +5 -3
- package/src/services/content/artist.ts +29 -31
- package/src/services/content/genre.ts +30 -38
- package/src/services/content/instructor.ts +28 -35
- package/test/lib/__snapshots__/filter.test.ts.snap +5 -0
- package/test/lib/filter.test.ts +1148 -0
- package/test/lib/{query.test.js → query.test.ts} +3 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module Genre
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import { getFieldsForContentType } from '../../contentTypeConfig.js'
|
|
5
5
|
import { fetchSanity, getSortOrder } from '../sanity.js'
|
|
6
|
-
import { FilterBuilder } from '../../filterBuilder.js'
|
|
7
6
|
import { Lesson } from './content'
|
|
8
7
|
import { BuildQueryOptions, query } from '../../lib/sanity/query'
|
|
9
8
|
import { Brands } from '../../lib/brands'
|
|
9
|
+
import { Filters as f } from '../../lib/sanity/filter'
|
|
10
10
|
|
|
11
11
|
export interface Genre {
|
|
12
12
|
name: string
|
|
@@ -35,27 +35,28 @@ export async function fetchGenres(
|
|
|
35
35
|
brand: Brands | string,
|
|
36
36
|
options: BuildQueryOptions = { sort: 'lower(name) asc' }
|
|
37
37
|
): Promise<Genres> {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
})
|
|
38
|
+
const lesson = f.combine(f.brand(brand), f.referencesParent())
|
|
39
|
+
const type = f.type('genre')
|
|
40
|
+
const lessonCount = `count(*[${lesson}])`
|
|
41
|
+
const postFilter = `lessonCount > 0`
|
|
41
42
|
|
|
42
43
|
const data = query()
|
|
43
|
-
.and(
|
|
44
|
+
.and(type)
|
|
44
45
|
.order(options?.sort || 'lower(name) asc')
|
|
45
|
-
.slice(options?.offset || 0,
|
|
46
|
+
.slice(options?.offset || 0, options?.limit || 20)
|
|
46
47
|
.select(
|
|
47
48
|
'name',
|
|
48
49
|
`"slug": slug.current`,
|
|
49
50
|
`"thumbnail": thumbnail_url.asset->url`,
|
|
50
|
-
`"lessons_count":
|
|
51
|
+
`"lessons_count": ${lessonCount}`
|
|
51
52
|
)
|
|
52
|
-
.postFilter(
|
|
53
|
+
.postFilter(postFilter)
|
|
53
54
|
.build()
|
|
54
55
|
|
|
55
56
|
const total = query()
|
|
56
|
-
.and(
|
|
57
|
-
.select(`"lessons_count":
|
|
58
|
-
.postFilter(
|
|
57
|
+
.and(type)
|
|
58
|
+
.select(`"lessons_count": ${lessonCount}`)
|
|
59
|
+
.postFilter(postFilter)
|
|
59
60
|
.build()
|
|
60
61
|
|
|
61
62
|
const q = `{
|
|
@@ -82,14 +83,11 @@ export async function fetchGenreBySlug(
|
|
|
82
83
|
slug: string,
|
|
83
84
|
brand?: Brands | string
|
|
84
85
|
): Promise<Genre | null> {
|
|
85
|
-
const
|
|
86
|
-
const filter = await new FilterBuilder(`${brandFilter} references(^._id)`, {
|
|
87
|
-
bypassPermissions: true,
|
|
88
|
-
}).buildFilter()
|
|
86
|
+
const filter = f.combine(brand ? f.brand(brand) : f.empty, f.referencesParent())
|
|
89
87
|
|
|
90
88
|
const q = query()
|
|
91
|
-
.and(
|
|
92
|
-
.and(
|
|
89
|
+
.and(f.type('genre'))
|
|
90
|
+
.and(f.slug(slug))
|
|
93
91
|
.select(
|
|
94
92
|
'name',
|
|
95
93
|
`"slug": slug.current`,
|
|
@@ -144,29 +142,23 @@ export async function fetchGenreLessons(
|
|
|
144
142
|
progressIds = [],
|
|
145
143
|
}: GenreLessonsOptions = {}
|
|
146
144
|
): Promise<GenreLessons> {
|
|
147
|
-
const fieldsString = getFieldsForContentType(contentType) as string
|
|
148
|
-
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"` : ''
|
|
149
|
-
const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
|
|
150
|
-
const addType = contentType ? `_type == '${contentType}' && ` : ''
|
|
151
|
-
const progressFilter =
|
|
152
|
-
progressIds.length > 0 ? `&& railcontent_id in [${progressIds.join(',')}]` : ''
|
|
153
|
-
const filter = `${addType} brand == '${brand}' ${searchFilter} ${includedFieldsFilter} && references(*[_type=='genre' && slug.current == '${slug}']._id) ${progressFilter}`
|
|
154
|
-
const filterWithRestrictions = await new FilterBuilder(filter).buildFilter()
|
|
155
|
-
|
|
156
145
|
sort = getSortOrder(sort, brand)
|
|
157
|
-
const data = query()
|
|
158
|
-
.and(filterWithRestrictions)
|
|
159
|
-
.order(sort)
|
|
160
|
-
.slice(offset, offset + limit)
|
|
161
|
-
.select(...(fieldsString ? [fieldsString] : []))
|
|
162
|
-
.build()
|
|
163
146
|
|
|
164
|
-
const
|
|
147
|
+
const restrictions = await f.combineAsync(
|
|
148
|
+
f.contentFilter(),
|
|
149
|
+
f.referencesIDWithFilter(f.combine(f.type('genre'), f.slug(slug)))
|
|
150
|
+
)
|
|
165
151
|
|
|
166
|
-
const q =
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
152
|
+
const q = query()
|
|
153
|
+
.and(f.brand(brand))
|
|
154
|
+
.and(f.searchMatch('title', searchTerm))
|
|
155
|
+
.and(f.includedFields(includedFields))
|
|
156
|
+
.and(f.progressIds(progressIds))
|
|
157
|
+
.and(restrictions)
|
|
158
|
+
.order(sort)
|
|
159
|
+
.slice(offset, limit)
|
|
160
|
+
.select(getFieldsForContentType(contentType) as string)
|
|
161
|
+
.build()
|
|
170
162
|
|
|
171
163
|
return fetchSanity(q, true, { processNeedAccess: false, processPageType: false })
|
|
172
164
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module Instructor
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import { filtersToGroq, getFieldsForContentType } from '../../contentTypeConfig.js'
|
|
4
|
+
import { getFieldsForContentType } from '../../contentTypeConfig.js'
|
|
6
5
|
import { fetchSanity, getSortOrder } from '../sanity.js'
|
|
7
6
|
import { Lesson } from './content'
|
|
8
7
|
import { BuildQueryOptions, query } from '../../lib/sanity/query'
|
|
9
8
|
import { Brands } from '../../lib/brands'
|
|
9
|
+
import { Filters as f } from '../../lib/sanity/filter'
|
|
10
10
|
|
|
11
11
|
export interface Instructor {
|
|
12
12
|
lessonCount: number
|
|
@@ -36,27 +36,28 @@ export async function fetchInstructors(
|
|
|
36
36
|
brand: Brands | string,
|
|
37
37
|
options: BuildQueryOptions
|
|
38
38
|
): Promise<Instructors> {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
})
|
|
39
|
+
const type = f.type('instructor')
|
|
40
|
+
const lesson = f.combine(f.brand(brand), f.referencesParent())
|
|
41
|
+
const lessonCount = `count(*[${lesson}])`
|
|
42
|
+
const postFilter = `lessonCount > 0`
|
|
42
43
|
|
|
43
44
|
const data = query()
|
|
44
|
-
.and(
|
|
45
|
+
.and(type)
|
|
45
46
|
.order(options?.sort || 'lower(name) asc')
|
|
46
|
-
.slice(options?.offset || 0,
|
|
47
|
+
.slice(options?.offset || 0, options?.limit || 20)
|
|
47
48
|
.select(
|
|
48
49
|
'name',
|
|
49
50
|
`"slug": slug.current`,
|
|
50
51
|
`"thumbnail": thumbnail_url.asset->url`,
|
|
51
|
-
`"lessonCount":
|
|
52
|
+
`"lessonCount": ${lessonCount}`
|
|
52
53
|
)
|
|
53
|
-
.postFilter(
|
|
54
|
+
.postFilter(postFilter)
|
|
54
55
|
.build()
|
|
55
56
|
|
|
56
57
|
const total = query()
|
|
57
|
-
.and(
|
|
58
|
-
.select(`"lessonCount":
|
|
59
|
-
.postFilter(
|
|
58
|
+
.and(type)
|
|
59
|
+
.select(`"lessonCount": ${lessonCount}`)
|
|
60
|
+
.postFilter(postFilter)
|
|
60
61
|
.build()
|
|
61
62
|
|
|
62
63
|
const q = `{
|
|
@@ -83,14 +84,11 @@ export async function fetchInstructorBySlug(
|
|
|
83
84
|
slug: string,
|
|
84
85
|
brand?: Brands | string
|
|
85
86
|
): Promise<Instructor | null> {
|
|
86
|
-
const
|
|
87
|
-
const filter = await new FilterBuilder(`${brandFilter} references(^._id)`, {
|
|
88
|
-
bypassPermissions: true,
|
|
89
|
-
}).buildFilter()
|
|
87
|
+
const filter = f.combine(brand ? f.brand(brand) : f.empty, f.referencesParent())
|
|
90
88
|
|
|
91
89
|
const q = query()
|
|
92
|
-
.and(
|
|
93
|
-
.and(
|
|
90
|
+
.and(f.type('instructor'))
|
|
91
|
+
.and(f.slug(slug))
|
|
94
92
|
.select(
|
|
95
93
|
'name',
|
|
96
94
|
`"slug": slug.current`,
|
|
@@ -143,27 +141,22 @@ export async function fetchInstructorLessons(
|
|
|
143
141
|
includedFields = [],
|
|
144
142
|
}: InstructorLessonsOptions = {}
|
|
145
143
|
): Promise<InstructorLessons> {
|
|
146
|
-
const fieldsString = getFieldsForContentType() as string
|
|
147
|
-
const searchFilter = searchTerm ? `&& title match "${searchTerm}*"` : ''
|
|
148
|
-
const includedFieldsFilter = includedFields.length > 0 ? filtersToGroq(includedFields) : ''
|
|
149
|
-
const filter = `brand == '${brand}' ${searchFilter} ${includedFieldsFilter} && references(*[_type=='instructor' && slug.current == '${slug}']._id)`
|
|
150
|
-
const filterWithRestrictions = await new FilterBuilder(filter).buildFilter()
|
|
151
|
-
|
|
152
144
|
sort = getSortOrder(sort, brand)
|
|
153
145
|
|
|
154
|
-
const
|
|
155
|
-
.
|
|
146
|
+
const restrictions = await f.combineAsync(
|
|
147
|
+
f.contentFilter(),
|
|
148
|
+
f.referencesIDWithFilter(f.combine(f.type('instructor'), f.slug(slug)))
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
const q = query()
|
|
152
|
+
.and(f.brand(brand))
|
|
153
|
+
.and(f.searchMatch('title', searchTerm))
|
|
154
|
+
.and(f.includedFields(includedFields))
|
|
155
|
+
.and(restrictions)
|
|
156
156
|
.order(sort)
|
|
157
|
-
.slice(offset,
|
|
158
|
-
.select(
|
|
157
|
+
.slice(offset, limit)
|
|
158
|
+
.select(getFieldsForContentType() as string)
|
|
159
159
|
.build()
|
|
160
160
|
|
|
161
|
-
const total = query().and(filterWithRestrictions).build()
|
|
162
|
-
|
|
163
|
-
const q = `{
|
|
164
|
-
"data": ${data},
|
|
165
|
-
"total": count(${total})
|
|
166
|
-
}`
|
|
167
|
-
|
|
168
161
|
return fetchSanity(q, true, { processNeedAccess: false, processPageType: false })
|
|
169
162
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Filters - Async Methods (Integration) Integration & Edge Cases snapshot: admin complete filter 1`] = `"status in ['draft','scheduled','published','archived','unlisted'] && published_on <= "2024-01-15T14:01:00.000Z" && !defined(deprecated_railcontent_id)"`;
|
|
4
|
+
|
|
5
|
+
exports[`Filters - Async Methods (Integration) Integration & Edge Cases snapshot: free user complete filter 1`] = `"status in ['scheduled','published'] && ((!defined(permission_v2) || count(permission_v2) == 0)) && published_on <= "2024-01-15T14:01:00.000Z" && !defined(deprecated_railcontent_id)"`;
|