Skip to content

Commit

Permalink
fix: reintroduce support for returnQuery option, default to false
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars committed Feb 14, 2024
1 parent 61257a9 commit dba1696
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 99 deletions.
26 changes: 26 additions & 0 deletions src/SanityClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ import type {
QueryOptions,
QueryParams,
QueryWithoutParams,
RawQuerylessQueryResponse,
RawQueryResponse,
RawRequestOptions,
SanityDocument,
SanityDocumentStub,
SingleMutationResult,
UnfilteredResponseQueryOptions,
UnfilteredResponseWithoutQuery,
} from './types'
import {ObservableUsersClient, UsersClient} from './users/UsersClient'

Expand Down Expand Up @@ -160,6 +162,18 @@ export class ObservableSanityClient {
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Observable<RawQueryResponse<R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<R = Any, Q extends QueryWithoutParams | QueryParams = QueryParams>(
query: string,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Observable<RawQuerylessQueryResponse<R>>
fetch<R, Q>(
query: string,
params?: Q,
Expand Down Expand Up @@ -799,6 +813,18 @@ export class SanityClient {
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Promise<RawQueryResponse<R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Request options
*/
fetch<R = Any, Q extends QueryWithoutParams | QueryParams = QueryParams>(
query: string,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Promise<RawQuerylessQueryResponse<R>>
fetch<R, Q>(query: string, params?: Q, options?: QueryOptions): Promise<RawQueryResponse<R> | R> {
return lastValueFrom(
dataMethods._fetch<R, Q>(
Expand Down
11 changes: 10 additions & 1 deletion src/data/dataMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,17 @@ export function _fetch<R, Q>(
const params = stega.enabled ? vercelStegaCleanAll(_params) : _params
const mapResponse =
options.filterResponse === false ? (res: Any) => res : (res: Any) => res.result

const {cache, next, ...opts} = {
// Opt out of setting a `signal` on an internal `fetch` if one isn't provided.
// This is necessary in React Server Components to avoid opting out of Request Memoization.
useAbortSignal: typeof options.signal !== 'undefined',
// Set `resultSourceMap' when stega is enabled, as it's required for encoding.
resultSourceMap: stega.enabled ? 'withKeyArraySelector' : options.resultSourceMap,
...options,
// Default to not returning the query, unless `filterResponse` is `false`,
// or `returnQuery` is explicitly set. `true` is the default in Content Lake, so skip if truthy
returnQuery: options.filterResponse === false && options.returnQuery !== false,
}
const reqOpts =
typeof cache !== 'undefined' || typeof next !== 'undefined'
Expand Down Expand Up @@ -253,7 +257,7 @@ export function _dataRequest(
const useGet = !isMutation && strQuery.length < getQuerySizeLimit
const stringQuery = useGet ? strQuery : ''
const returnFirst = options.returnFirst
const {timeout, token, tag, headers} = options
const {timeout, token, tag, headers, returnQuery} = options

const uri = _getDataUrl(client, endpoint, stringQuery)

Expand All @@ -267,6 +271,7 @@ export function _dataRequest(
headers,
token,
tag,
returnQuery,
perspective: options.perspective,
resultSourceMap: options.resultSourceMap,
canUseCdn: isQuery,
Expand Down Expand Up @@ -369,6 +374,10 @@ export function _requestObservable<R>(
printCdnPreviewDraftsWarning()
}
}

if (options.returnQuery === false) {
options.query = {returnQuery: 'false', ...options.query}
}
}

const reqOptions = requestOptions(
Expand Down
5 changes: 4 additions & 1 deletion src/data/encodeQueryString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const encodeQueryString = ({
}) => {
const searchParams = new URLSearchParams()
// We generally want tag at the start of the query string
const {tag, ...opts} = options
const {tag, returnQuery, ...opts} = options
// We're using `append` instead of `set` to support React Native: https://github.com/facebook/react-native/blob/1982c4722fcc51aa87e34cf562672ee4aff540f1/packages/react-native/Libraries/Blob/URL.js#L86-L88
if (tag) searchParams.append('tag', tag)
searchParams.append('query', query)
Expand All @@ -26,5 +26,8 @@ export const encodeQueryString = ({
if (value) searchParams.append(key, `${value}`)
}

// `returnQuery` is default `true`, so needs an explicit `false` handling
if (returnQuery === false) searchParams.append('returnQuery', 'false')

return `?${searchParams}`
}
30 changes: 29 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export interface RequestObservableOptions extends Omit<RequestOptions, 'url'> {
canUseCdn?: boolean
useCdn?: boolean
tag?: string
returnQuery?: boolean
resultSourceMap?: boolean | 'withKeyArraySelector'
perspective?: ClientPerspective
}
Expand Down Expand Up @@ -452,6 +453,8 @@ export interface QueryParams {
/** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
resultSourceMap?: never
/** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
returnQuery?: never
/** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
signal?: never
/** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
stega?: never
Expand Down Expand Up @@ -721,6 +724,7 @@ export interface ListenOptions {
export interface ResponseQueryOptions extends RequestOptions {
perspective?: ClientPerspective
resultSourceMap?: boolean | 'withKeyArraySelector'
returnQuery?: boolean
useCdn?: boolean
stega?: boolean | StegaConfig
// The `cache` and `next` options are specific to the Next.js App Router integration
Expand All @@ -736,10 +740,31 @@ export interface FilteredResponseQueryOptions extends ResponseQueryOptions {
/** @public */
export interface UnfilteredResponseQueryOptions extends ResponseQueryOptions {
filterResponse: false

/**
* When `filterResponse` is `false`, `returnQuery` also defaults to `true` for
* backwards compatibility (on the client side, not from the content lake API).
* Can also explicitly be set to `true`.
*/
returnQuery?: true
}

/**
* When using `filterResponse: false`, but you do not wish to receive back the query from
* the content lake API.
*
* @public
*/
export interface UnfilteredResponseWithoutQuery extends ResponseQueryOptions {
filterResponse: false
returnQuery: false
}

/** @public */
export type QueryOptions = FilteredResponseQueryOptions | UnfilteredResponseQueryOptions
export type QueryOptions =
| FilteredResponseQueryOptions
| UnfilteredResponseQueryOptions
| UnfilteredResponseWithoutQuery

/** @public */
export interface RawQueryResponse<R> {
Expand All @@ -749,6 +774,9 @@ export interface RawQueryResponse<R> {
resultSourceMap?: ContentSourceMap
}

/** @public */
export type RawQuerylessQueryResponse<R> = Omit<RawQueryResponse<R>, 'query'>

/** @internal */
export type BaseMutationOptions = RequestOptions & {
visibility?: 'sync' | 'async' | 'deferred'
Expand Down
15 changes: 14 additions & 1 deletion test-next/client.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/// <reference types="next/types/global" />

import {createClient, QueryOptions, QueryParams, RawQueryResponse} from '@sanity/client'
import {
createClient,
type QueryOptions,
type QueryParams,
type RawQuerylessQueryResponse,
type RawQueryResponse,
} from '@sanity/client'
import {describe, expectTypeOf, test} from 'vitest'

describe('client.fetch', () => {
Expand Down Expand Up @@ -33,6 +39,13 @@ describe('client.fetch', () => {
{filterResponse: false, cache: 'force-cache', next: {revalidate: 60, tags: ['post']}},
),
).toMatchTypeOf<RawQueryResponse<any>>()
expectTypeOf(
await client.fetch(
'*[_type == $type]',
{type: 'post'},
{filterResponse: false, returnQuery: false},
),
).toMatchTypeOf<RawQuerylessQueryResponse<any>>()
})
test('generics', async () => {
expectTypeOf(
Expand Down
Loading

0 comments on commit dba1696

Please sign in to comment.