Skip to content

Commit

Permalink
fix(query): ensure default values always apply to query params (#1778)
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz authored Dec 29, 2022
1 parent 8624e85 commit 30c26e3
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 68 deletions.
18 changes: 6 additions & 12 deletions src/runtime/composables/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@ import { addPrerenderPath, shouldUseClientDB, withContentBase } from './utils'
export const fetchContentNavigation = async (queryBuilder?: QueryBuilder | QueryBuilderParams): Promise<Array<NavItem>> => {
const { content } = useRuntimeConfig().public

// When params is an instance of QueryBuilder then we need to pick the params explicitly
const params: QueryBuilderParams = typeof queryBuilder?.params === 'function' ? queryBuilder.params() : queryBuilder || {}

// Filter by locale if:
// - locales are defined
// - query doesn't already have a locale filter
if (content.locales.length) {
const queryLocale = params.where?.find(w => w._locale)?._locale
if (!queryLocale) {
params.where = params.where || []
params.where.push({ _locale: content.defaultLocale })
}
// Ensure that queryBuilder is an instance of QueryBuilder
if (typeof queryBuilder?.params !== 'function') {
queryBuilder = queryContent(queryBuilder as QueryBuilderParams)
}

// Get query params from queryBuilder instance to ensure default values are applied
const params: QueryBuilderParams = queryBuilder.params()

const apiPath = content.experimental.stripQueryParameters
? withContentBase(`/navigation/${process.dev ? '_' : `${hash(params)}.${content.integrity}`}/${encodeQueryParams(params)}.json`)
: withContentBase(process.dev ? `/navigation/${hash(params)}` : `/navigation/${hash(params)}.${content.integrity}.json`)
Expand Down
68 changes: 42 additions & 26 deletions src/runtime/composables/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,8 @@ import { addPrerenderPath, shouldUseClientDB, withContentBase } from './utils'
/**
* Query fetcher
*/
export const createQueryFetch = <T = ParsedContent>(path?: string) => async (query: QueryBuilder<T>) => {
export const createQueryFetch = <T = ParsedContent>() => async (query: QueryBuilder<T>) => {
const { content } = useRuntimeConfig().public
if (path) {
if (query.params().first && (query.params().where || []).length === 0) {
// If query contains `path` and does not contain any `where` condition
// Then can use `path` as `where` condition to find exact match
query.where({ _path: withoutTrailingSlash(path) })
} else {
query.where({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, '\\$&')}`) })
}
}
// Provide default sort order
if (!query.params().sort?.length) {
query.sort({ _file: 1, $numeric: true })
}

// Filter by locale if:
// - locales are defined
// - query doesn't already have a locale filter
if (content.locales.length) {
const queryLocale = query.params().where?.find(w => w._locale)?._locale
if (!queryLocale) {
query.locale(content.defaultLocale)
}
}

const params = query.params()

Expand Down Expand Up @@ -79,9 +56,48 @@ export function queryContent<T = ParsedContent>(): QueryBuilder<T>;
export function queryContent<T = ParsedContent>(query: string, ...pathParts: string[]): QueryBuilder<T>;
export function queryContent<T = ParsedContent> (query: QueryBuilderParams): QueryBuilder<T>;
export function queryContent<T = ParsedContent> (query?: string | QueryBuilderParams, ...pathParts: string[]) {
const { content } = useRuntimeConfig().public
const queryBuilder = createQuery<T>(createQueryFetch(), typeof query !== 'string' ? query : {})
let path: string

if (typeof query === 'string') {
return createQuery<T>(createQueryFetch(withLeadingSlash(joinURL(query, ...pathParts))))
path = withLeadingSlash(joinURL(query, ...pathParts))
}

const originalParamsFn = queryBuilder.params
queryBuilder.params = () => {
const params = originalParamsFn()

// Add `path` as `where` condition
if (path) {
params.where = params.where || []
if (params.first && (params.where || []).length === 0) {
// If query contains `path` and does not contain any `where` condition
// Then can use `path` as `where` condition to find exact match
params.where.push({ _path: withoutTrailingSlash(path) })
} else {
params.where.push({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, '\\$&')}`) })
}
}

// Provide default sort order
if (!params.sort?.length) {
params.sort = [{ _file: 1, $numeric: true }]
}

// Filter by locale if:
// - locales are defined
// - query doesn't already have a locale filter
if (content.locales.length) {
const queryLocale = params.where?.find(w => w._locale)?._locale
if (!queryLocale) {
params.where = params.where || []
params.where.push({ _locale: content.defaultLocale })
}
}

return params
}

return createQuery<T>(createQueryFetch(), query)
return queryBuilder
}
74 changes: 44 additions & 30 deletions src/runtime/server/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,30 +185,7 @@ export async function parseContent (id: string, content: string, opts: ParseCont
return result
}

export const createServerQueryFetch = <T = ParsedContent>(event: H3Event, path?: string) => (query: QueryBuilder<T>) => {
if (path) {
if (query.params().first) {
query.where({ _path: withoutTrailingSlash(path) })
} else {
query.where({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, '\\$&')}`) })
}
}

// Provide default sort order
if (!query.params().sort?.length) {
query.sort({ _file: 1, $numeric: true })
}

// Filter by locale if:
// - locales are defined
// - query doesn't already have a locale filter
if (contentConfig.locales.length) {
const queryLocale = query.params().where?.find(w => w._locale)?._locale
if (!queryLocale) {
query.locale(contentConfig.defaultLocale)
}
}

export const createServerQueryFetch = <T = ParsedContent>(event: H3Event) => (query: QueryBuilder<T>) => {
return createPipelineFetcher<T>(() => getIndexedContentsList<T>(event, query))(query)
}

Expand All @@ -217,12 +194,49 @@ export const createServerQueryFetch = <T = ParsedContent>(event: H3Event, path?:
*/
export function serverQueryContent<T = ParsedContent>(event: H3Event): QueryBuilder<T>;
export function serverQueryContent<T = ParsedContent>(event: H3Event, params?: QueryBuilderParams): QueryBuilder<T>;
export function serverQueryContent<T = ParsedContent>(event: H3Event, path?: string, ...pathParts: string[]): QueryBuilder<T>;
export function serverQueryContent<T = ParsedContent> (event: H3Event, path?: string | QueryBuilderParams, ...pathParts: string[]) {
if (typeof path === 'string') {
path = withLeadingSlash(joinURL(path, ...pathParts))
return createQuery<T>(createServerQueryFetch(event, path))
export function serverQueryContent<T = ParsedContent>(event: H3Event, query?: string, ...pathParts: string[]): QueryBuilder<T>;
export function serverQueryContent<T = ParsedContent> (event: H3Event, query?: string | QueryBuilderParams, ...pathParts: string[]) {
const queryBuilder = createQuery<T>(createServerQueryFetch(event), typeof query !== 'string' ? query || {} : {})
let path: string

if (typeof query === 'string') {
path = withLeadingSlash(joinURL(query, ...pathParts))
}

const originalParamsFn = queryBuilder.params
queryBuilder.params = () => {
const params = originalParamsFn()

// Add `path` as `where` condition
if (path) {
params.where = params.where || []
if (params.first && (params.where || []).length === 0) {
// If query contains `path` and does not contain any `where` condition
// Then can use `path` as `where` condition to find exact match
params.where.push({ _path: withoutTrailingSlash(path) })
} else {
params.where.push({ _path: new RegExp(`^${path.replace(/[-[\]{}()*+.,^$\s/]/g, '\\$&')}`) })
}
}

// Provide default sort order
if (!params.sort?.length) {
params.sort = [{ _file: 1, $numeric: true }]
}

// Filter by locale if:
// - locales are defined
// - query doesn't already have a locale filter
if (contentConfig.locales.length) {
const queryLocale = params.where?.find(w => w._locale)?._locale
if (!queryLocale) {
params.where = params.where || []
params.where.push({ _locale: contentConfig.defaultLocale })
}
}

return params
}

return createQuery<T>(createServerQueryFetch(event), path || {})
return queryBuilder
}

0 comments on commit 30c26e3

Please sign in to comment.