musora-content-services 2.102.1 → 2.102.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/CHANGELOG.md +14 -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 -31
- package/src/services/content/instructor.ts +28 -28
- 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,24 +142,25 @@ 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)
|
|
146
|
+
|
|
147
|
+
const restrictions = await f.combineAsync(
|
|
148
|
+
f.contentFilter(),
|
|
149
|
+
f.referencesIDWithFilter(f.combine(f.type('genre'), f.slug(slug)))
|
|
150
|
+
)
|
|
151
|
+
|
|
157
152
|
const data = query()
|
|
158
|
-
.and(
|
|
153
|
+
.and(f.brand(brand))
|
|
154
|
+
.and(f.searchMatch('title', searchTerm))
|
|
155
|
+
.and(f.includedFields(includedFields))
|
|
156
|
+
.and(f.progressIds(progressIds))
|
|
157
|
+
.and(restrictions)
|
|
159
158
|
.order(sort)
|
|
160
|
-
.slice(offset,
|
|
161
|
-
.select(
|
|
159
|
+
.slice(offset, limit)
|
|
160
|
+
.select(getFieldsForContentType(contentType) as string)
|
|
162
161
|
.build()
|
|
163
162
|
|
|
164
|
-
const total = query().and(
|
|
163
|
+
const total = query().and(restrictions).build()
|
|
165
164
|
|
|
166
165
|
const q = `{
|
|
167
166
|
"data": ${data},
|
|
@@ -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,22 +141,24 @@ 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
|
|
|
146
|
+
const restrictions = await f.combineAsync(
|
|
147
|
+
f.contentFilter(),
|
|
148
|
+
f.referencesIDWithFilter(f.combine(f.type('instructor'), f.slug(slug)))
|
|
149
|
+
)
|
|
150
|
+
|
|
154
151
|
const data = query()
|
|
155
|
-
.and(
|
|
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(
|
|
161
|
+
const total = query().and(restrictions).build()
|
|
162
162
|
|
|
163
163
|
const q = `{
|
|
164
164
|
"data": ${data},
|
|
@@ -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)"`;
|