diff --git a/src/SanityClient.ts b/src/SanityClient.ts index d6eaf0e7..54f09aa8 100644 --- a/src/SanityClient.ts +++ b/src/SanityClient.ts @@ -28,14 +28,12 @@ import type { QueryOptions, QueryParams, QueryWithoutParams, - RawQuerylessQueryResponse, RawQueryResponse, RawRequestOptions, SanityDocument, SanityDocumentStub, SingleMutationResult, UnfilteredResponseQueryOptions, - UnfilteredResponseWithoutQuery, } from './types' import {ObservableUsersClient, UsersClient} from './users/UsersClient' @@ -162,18 +160,6 @@ export class ObservableSanityClient { params: Q extends QueryWithoutParams ? QueryWithoutParams : Q, options: UnfilteredResponseQueryOptions, ): Observable> - /** - * Perform a GROQ-query against the configured dataset. - * - * @param query - GROQ-query to perform - * @param params - Optional query parameters - * @param options - Request options - */ - fetch( - query: string, - params: Q extends QueryWithoutParams ? QueryWithoutParams : Q, - options: UnfilteredResponseWithoutQuery, - ): Observable> fetch( query: string, params?: Q, @@ -813,18 +799,6 @@ export class SanityClient { params: Q extends QueryWithoutParams ? QueryWithoutParams : Q, options: UnfilteredResponseQueryOptions, ): Promise> - /** - * Perform a GROQ-query against the configured dataset. - * - * @param query - GROQ-query to perform - * @param params - Optional query parameters - * @param options - Request options - */ - fetch( - query: string, - params: Q extends QueryWithoutParams ? QueryWithoutParams : Q, - options: UnfilteredResponseWithoutQuery, - ): Promise> fetch(query: string, params?: Q, options?: QueryOptions): Promise | R> { return lastValueFrom( dataMethods._fetch( diff --git a/src/data/dataMethods.ts b/src/data/dataMethods.ts index 7be74b35..fa4d6239 100644 --- a/src/data/dataMethods.ts +++ b/src/data/dataMethods.ts @@ -80,11 +80,6 @@ export function _fetch( const params = stega.enabled ? vercelStegaCleanAll(_params) : _params const mapResponse = options.filterResponse === false ? (res: Any) => res : (res: Any) => res.result - - // 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 - const returnQuery = options.filterResponse === false && options.returnQuery !== false - 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. @@ -98,13 +93,7 @@ export function _fetch( ? {...opts, fetch: {cache, next}} : opts - const $request = _dataRequest( - client, - httpRequest, - 'query', - {query, params, options: {returnQuery}}, - reqOpts, - ) + const $request = _dataRequest(client, httpRequest, 'query', {query, params}, reqOpts) return stega.enabled ? $request.pipe( combineLatestWith( diff --git a/src/data/encodeQueryString.ts b/src/data/encodeQueryString.ts index 613d8eaf..3c9711a1 100644 --- a/src/data/encodeQueryString.ts +++ b/src/data/encodeQueryString.ts @@ -11,7 +11,7 @@ export const encodeQueryString = ({ }) => { const searchParams = new URLSearchParams() // We generally want tag at the start of the query string - const {tag, returnQuery, ...opts} = options + const {tag, ...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) @@ -26,8 +26,5 @@ 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}` } diff --git a/src/types.ts b/src/types.ts index c9975356..169d00b2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -452,8 +452,6 @@ 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 @@ -723,7 +721,6 @@ 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 @@ -739,31 +736,10 @@ 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 - | UnfilteredResponseWithoutQuery +export type QueryOptions = FilteredResponseQueryOptions | UnfilteredResponseQueryOptions /** @public */ export interface RawQueryResponse { @@ -773,9 +749,6 @@ export interface RawQueryResponse { resultSourceMap?: ContentSourceMap } -/** @public */ -export type RawQuerylessQueryResponse = Omit, 'query'> - /** @internal */ export type BaseMutationOptions = RequestOptions & { visibility?: 'sync' | 'async' | 'deferred' diff --git a/test-next/client.test-d.ts b/test-next/client.test-d.ts index 1fe5e23d..24c43ae0 100644 --- a/test-next/client.test-d.ts +++ b/test-next/client.test-d.ts @@ -1,12 +1,6 @@ /// -import { - createClient, - type QueryOptions, - type QueryParams, - type RawQuerylessQueryResponse, - type RawQueryResponse, -} from '@sanity/client' +import {createClient, QueryOptions, QueryParams, RawQueryResponse} from '@sanity/client' import {describe, expectTypeOf, test} from 'vitest' describe('client.fetch', () => { @@ -39,13 +33,6 @@ describe('client.fetch', () => { {filterResponse: false, cache: 'force-cache', next: {revalidate: 60, tags: ['post']}}, ), ).toMatchTypeOf>() - expectTypeOf( - await client.fetch( - '*[_type == $type]', - {type: 'post'}, - {filterResponse: false, returnQuery: false}, - ), - ).toMatchTypeOf>() }) test('generics', async () => { expectTypeOf( diff --git a/test/client.test.ts b/test/client.test.ts index 8354e001..efdaaf72 100644 --- a/test/client.test.ts +++ b/test/client.test.ts @@ -508,8 +508,9 @@ describe('client', async () => { const qs = 'beerfiesta.beer%5B.title%20%3D%3D%20%24beerName%5D&%24beerName=%22Headroom%20Double%20IPA%22' - nock(projectHost()).get(`/v1/data/query/foo?query=${qs}&returnQuery=false`).reply(200, { + nock(projectHost()).get(`/v1/data/query/foo?query=${qs}`).reply(200, { ms: 123, + query: query, result, }) @@ -526,7 +527,7 @@ describe('client', async () => { nock(projectHost()).get(`/v1/data/query/foo?query=${qs}`).reply(200, { ms: 123, - query, + query: query, result, }) @@ -537,33 +538,13 @@ describe('client', async () => { expect(res.result[0].rating, 'data should match').toBe(5) }) - test.skipIf(isEdge)('can explicitly ask to include query in response', async () => { - const query = 'beerfiesta.beer[.title == $beerName]' - const params = {beerName: 'Headroom Double IPA'} - const qs = - 'beerfiesta.beer%5B.title%20%3D%3D%20%24beerName%5D&%24beerName=%22Headroom%20Double%20IPA%22' - - nock(projectHost()).get(`/v1/data/query/foo?query=${qs}`).reply(200, { + test.skipIf(isEdge)('can query for documents with request tag', async () => { + nock(projectHost()).get(`/v1/data/query/foo?query=*&tag=mycompany.syncjob`).reply(200, { ms: 123, - query, + query: '*', result, }) - const res = await getClient().fetch(query, params, {filterResponse: false, returnQuery: true}) - expect(res.ms, 'should include timing info').toBe(123) - expect(res.query, 'should include query').toBe(query) - expect(res.result.length, 'length should match').toBe(1) - expect(res.result[0].rating, 'data should match').toBe(5) - }) - - test.skipIf(isEdge)('can query for documents with request tag', async () => { - nock(projectHost()) - .get(`/v1/data/query/foo?query=*&tag=mycompany.syncjob&returnQuery=false`) - .reply(200, { - ms: 123, - result, - }) - const res = await getClient().fetch('*', {}, {tag: 'mycompany.syncjob'}) expect(res.length, 'length should match').toBe(1) expect(res[0].rating, 'data should match').toBe(5) @@ -573,11 +554,10 @@ describe('client', async () => { 'can query for documents with resultSourceMap and perspective', async () => { nock(projectHost()) - .get( - `/vX/data/query/foo?query=*&returnQuery=false&resultSourceMap=true&perspective=previewDrafts`, - ) + .get(`/vX/data/query/foo?query=*&resultSourceMap=true&perspective=previewDrafts`) .reply(200, { ms: 123, + query: '*', result, resultSourceMap, }) @@ -598,10 +578,11 @@ describe('client', async () => { async () => { nock(projectHost()) .get( - `/vX/data/query/foo?query=*&returnQuery=false&resultSourceMap=withKeyArraySelector&perspective=previewDrafts`, + `/vX/data/query/foo?query=*&resultSourceMap=withKeyArraySelector&perspective=previewDrafts`, ) .reply(200, { ms: 123, + query: '*', result, resultSourceMap, }) @@ -619,9 +600,10 @@ describe('client', async () => { test.skipIf(isEdge)('automatically useCdn false if perspective is previewDrafts', async () => { nock('https://abc123.api.sanity.io') - .get(`/v1/data/query/foo?query=*&returnQuery=false&perspective=previewDrafts`) + .get(`/v1/data/query/foo?query=*&perspective=previewDrafts`) .reply(200, { ms: 123, + query: '*', result, }) @@ -640,11 +622,10 @@ describe('client', async () => { 'can query for documents with resultSourceMap and perspective using the third client.fetch parameter', async () => { nock(projectHost()) - .get( - `/vX/data/query/foo?query=*&returnQuery=false&resultSourceMap=true&perspective=previewDrafts`, - ) + .get(`/vX/data/query/foo?query=*&resultSourceMap=true&perspective=previewDrafts`) .reply(200, { ms: 123, + query: '*', result, resultSourceMap, }) @@ -663,13 +644,12 @@ describe('client', async () => { test.skipIf(isEdge)( 'setting resultSourceMap and perspective on client.fetch overrides the config', async () => { - nock(projectHost()) - .get(`/vX/data/query/foo?query=*&returnQuery=false&perspective=published`) - .reply(200, { - ms: 123, - result, - resultSourceMap, - }) + nock(projectHost()).get(`/vX/data/query/foo?query=*&perspective=published`).reply(200, { + ms: 123, + query: '*', + result, + resultSourceMap, + }) const client = getClient({ apiVersion: 'X', @@ -686,9 +666,10 @@ describe('client', async () => { 'setting a perspective previewDrafts override on client.fetch sets useCdn to false', async () => { nock('https://abc123.api.sanity.io') - .get(`/v1/data/query/foo?query=*&returnQuery=false&perspective=previewDrafts`) + .get(`/v1/data/query/foo?query=*&perspective=previewDrafts`) .reply(200, { ms: 123, + query: '*', result, }) @@ -700,12 +681,11 @@ describe('client', async () => { ) test.skipIf(isEdge)('allow overriding useCdn to false on client.fetch', async () => { - nock('https://abc123.api.sanity.io') - .get(`/v1/data/query/foo?query=*&returnQuery=false`) - .reply(200, { - ms: 123, - result, - }) + nock('https://abc123.api.sanity.io').get(`/v1/data/query/foo?query=*`).reply(200, { + ms: 123, + query: '*', + result, + }) const client = createClient({projectId: 'abc123', dataset: 'foo', useCdn: true}) const res = await client.fetch('*', {}, {useCdn: false}) @@ -714,12 +694,11 @@ describe('client', async () => { }) test.skipIf(isEdge)('allow overriding useCdn to true on client.fetch', async () => { - nock('https://abc123.apicdn.sanity.io') - .get(`/v1/data/query/foo?query=*&returnQuery=false`) - .reply(200, { - ms: 123, - result, - }) + nock('https://abc123.apicdn.sanity.io').get(`/v1/data/query/foo?query=*`).reply(200, { + ms: 123, + query: '*', + result, + }) const client = createClient({projectId: 'abc123', dataset: 'foo', useCdn: false}) const res = await client.fetch('*', {}, {useCdn: true}) @@ -728,19 +707,23 @@ describe('client', async () => { }) test.skipIf(isEdge)('throws on invalid request tag on request', () => { + nock(projectHost()).get(`/v1/data/query/foo?query=*&tag=mycompany.syncjob`).reply(200, { + ms: 123, + query: '*', + result, + }) + expect(() => { getClient().fetch('*', {}, {tag: 'mycompany syncjob ok'}) }).toThrow(/tag can only contain alphanumeric/i) }) test.skipIf(isEdge)('can use a tag-prefixed client', async () => { - nock(projectHost()) - .get(`/v1/data/query/foo?query=*&returnQuery=false&tag=mycompany.syncjob`) - .reply(200, { - ms: 123, - query: '*', - result, - }) + nock(projectHost()).get(`/v1/data/query/foo?query=*&tag=mycompany.syncjob`).reply(200, { + ms: 123, + query: '*', + result, + }) const res = await getClient({requestTagPrefix: 'mycompany'}).fetch('*', {}, {tag: 'syncjob'}) expect(res.length, 'length should match').toBe(1) @@ -756,10 +739,7 @@ describe('client', async () => { message: 'You are not allowed to access this resource', } - nock(projectHost()) - .get('/v1/data/query/foo?query=area51&returnQuery=false') - .times(5) - .reply(403, response) + nock(projectHost()).get('/v1/data/query/foo?query=area51').times(5).reply(403, response) try { await getClient().fetch('area51') @@ -786,7 +766,7 @@ describe('client', async () => { } nock(projectHost()) - .get('/v1/data/query/foo?query=foo.bar.baz%20%2012%23%5B%7B&returnQuery=false') + .get('/v1/data/query/foo?query=foo.bar.baz%20%2012%23%5B%7B') .reply(400, response) try { @@ -1200,7 +1180,7 @@ describe('client', async () => { test.skipIf(isEdge)('delete() can use query with params', async () => { const query = '*[_type == "beer" && title == $beerName]' const params = {beerName: 'Headroom Double IPA'} - const expectedBody = {mutations: [{delete: {query, params: params}}]} + const expectedBody = {mutations: [{delete: {query: query, params: params}}]} nock(projectHost()) .post( '/v1/data/mutate/foo?returnIds=true&returnDocuments=true&visibility=sync', @@ -1208,7 +1188,7 @@ describe('client', async () => { ) .reply(200, {transactionId: 'abc123'}) - await expect(getClient().delete({query, params: params})).resolves.not.toThrow() + await expect(getClient().delete({query: query, params: params})).resolves.not.toThrow() }) test.skipIf(isEdge)('delete() can be told not to return documents', async () => { @@ -1395,9 +1375,10 @@ describe('client', async () => { nock(projectHost()) .get('/v1/data/query/foo') - .query({query, ...qParams, returnQuery: 'false'}) + .query({query, ...qParams}) .reply(200, { ms: 123, + query: query, result, }) @@ -1423,7 +1404,7 @@ describe('client', async () => { .post('/v1/data/query/foo', '*') .reply(200, { ms: 123, - query, + query: query, result, }) @@ -1454,7 +1435,7 @@ describe('client', async () => { .post('/v1/data/query/foo', '*') .reply(200, { ms: 123, - query, + query: query, result, }) @@ -1481,7 +1462,7 @@ describe('client', async () => { .post('/v1/data/query/foo?tag=myapp.silly-query', '*') .reply(200, { ms: 123, - query, + query: query, result, }) @@ -1509,7 +1490,7 @@ describe('client', async () => { .post('/vX/data/query/foo?resultSourceMap=true&perspective=previewDrafts', '*') .reply(200, { ms: 123, - query, + query: query, result, resultSourceMap, }) @@ -1542,7 +1523,7 @@ describe('client', async () => { .post('/v1/data/query/foo', '*') .reply(200, { ms: 123, - query, + query: query, result, }) @@ -2579,9 +2560,7 @@ describe('client', async () => { const client = createClient({projectId: 'abc123', dataset: 'foo'}) const response = {result: []} - nock('https://abc123.apicdn.sanity.io') - .get('/v1/data/query/foo?query=*&returnQuery=false') - .reply(200, response) + nock('https://abc123.apicdn.sanity.io').get('/v1/data/query/foo?query=*').reply(200, response) const docs = await client.fetch('*') expect(docs.length).toEqual(0) @@ -2591,9 +2570,7 @@ describe('client', async () => { const client = createClient({projectId: 'abc123', dataset: 'foo', useCdn: false}) const response = {result: []} - nock('https://abc123.api.sanity.io') - .get('/v1/data/query/foo?query=*&returnQuery=false') - .reply(200, response) + nock('https://abc123.api.sanity.io').get('/v1/data/query/foo?query=*').reply(200, response) const docs = await client.fetch('*') expect(docs.length).toEqual(0) @@ -2619,7 +2596,7 @@ describe('client', async () => { const reqheaders = {Authorization: 'Bearer foo'} nock('https://abc123.apicdn.sanity.io', {reqheaders}) - .get('/v1/data/query/foo?query=*&returnQuery=false') + .get('/v1/data/query/foo?query=*') .reply(200, {result: []}) await expect(client.fetch('*')).resolves.not.toThrow() @@ -2635,7 +2612,7 @@ describe('client', async () => { const reqheaders = {foo: 'bar'} nock('https://abc123.api.sanity.io', {reqheaders}) - .get('/v1/data/query/foo?query=*&returnQuery=false') + .get('/v1/data/query/foo?query=*') .reply(200, {result: []}) await expect(client.fetch('*', {}, {headers: {foo: 'bar'}})).resolves.not.toThrow() @@ -2650,7 +2627,7 @@ describe('client', async () => { }) nock('https://abc123.api.sanity.io') - .get('/v1/data/query/foo?query=*&returnQuery=false') + .get('/v1/data/query/foo?query=*') .reply(200, {result: []}) await expect(client.fetch('*')).resolves.not.toThrow() @@ -2659,7 +2636,7 @@ describe('client', async () => { describe('HTTP REQUESTS', () => { test.skipIf(isEdge)('includes token if set', async () => { - const qs = '?query=foo.bar&returnQuery=false' + const qs = '?query=foo.bar' const token = 'abcdefghijklmnopqrstuvwxyz' const reqheaders = {Authorization: `Bearer ${token}`} nock(projectHost(), {reqheaders}).get(`/v1/data/query/foo${qs}`).reply(200, {result: []}) @@ -2669,7 +2646,7 @@ describe('client', async () => { }) test.skipIf(isEdge)('allows overriding token', async () => { - const qs = '?query=foo.bar&returnQuery=false' + const qs = '?query=foo.bar' const token = 'abcdefghijklmnopqrstuvwxyz' const override = '123456789' const reqheaders = {Authorization: `Bearer ${override}`} @@ -2680,7 +2657,7 @@ describe('client', async () => { }) test.skipIf(isEdge)('allows overriding timeout', async () => { - const qs = `?query=${encodeURIComponent('*[][0]')}&returnQuery=false` + const qs = `?query=${encodeURIComponent('*[][0]')}` nock(projectHost()).get(`/v1/data/query/foo${qs}`).reply(200, {result: []}) const docs = await getClient().fetch('*[][0]', {}, {timeout: 60 * 1000}) diff --git a/test/stega/client.test.ts b/test/stega/client.test.ts index cc7116a1..468fb804 100644 --- a/test/stega/client.test.ts +++ b/test/stega/client.test.ts @@ -131,10 +131,8 @@ describe('@sanity/client/stega', async () => { test.skipIf(isEdge)('it returns stega strings in the response', async () => { nock(projectHost()) - .get( - `/v1/data/query/foo?query=${qs}&returnQuery=false&resultSourceMap=withKeyArraySelector`, - ) - .reply(200, {ms: 123, result, resultSourceMap}) + .get(`/v1/data/query/foo?query=${qs}&resultSourceMap=withKeyArraySelector`) + .reply(200, {ms: 123, query, result, resultSourceMap}) const res = await getClient({stega: {enabled: true, studioUrl: '/studio'}}).fetch( query, @@ -166,10 +164,8 @@ describe('@sanity/client/stega', async () => { test.skipIf(isEdge)('it strips stega strings from params', async () => { nock(projectHost()) - .get( - `/v1/data/query/foo?query=${qs}&returnQuery=false&resultSourceMap=withKeyArraySelector`, - ) - .reply(200, {ms: 123, result, resultSourceMap}) + .get(`/v1/data/query/foo?query=${qs}&resultSourceMap=withKeyArraySelector`) + .reply(200, {ms: 123, query, result, resultSourceMap}) const res = await getClient({stega: {enabled: true, studioUrl: '/studio'}}).fetch(query, { id: vercelStegaCombine(params.id, JSON.stringify({origin: 'sanity.io', href: '/studio'})), @@ -181,10 +177,8 @@ describe('@sanity/client/stega', async () => { describe.skipIf(isEdge)('client.fetch', async () => { test('the stega option accepts booleans as a shortcut to toggle `enabled`', async () => { nock(projectHost()) - .get( - `/v1/data/query/foo?query=${qs}&returnQuery=false&resultSourceMap=withKeyArraySelector`, - ) - .reply(200, {ms: 123, result, resultSourceMap}) + .get(`/v1/data/query/foo?query=${qs}&resultSourceMap=withKeyArraySelector`) + .reply(200, {ms: 123, query, result, resultSourceMap}) const res = await getClient({stega: {studioUrl}}).fetch(query, params, { stega: true, @@ -205,8 +199,8 @@ describe('@sanity/client/stega', async () => { test('the stega option accepts booleans as a shortcut to toggle `enabled`', async () => { nock(projectHost()) - .get(`/v1/data/query/foo?query=${qs}&returnQuery=false`) - .reply(200, {ms: 123, result, resultSourceMap}) + .get(`/v1/data/query/foo?query=${qs}`) + .reply(200, {ms: 123, query, result, resultSourceMap}) const res = await getClient({stega: {studioUrl, enabled: true}}).fetch(query, params, { stega: false, @@ -216,10 +210,8 @@ describe('@sanity/client/stega', async () => { test('the stega option merges in defaults', async () => { nock(projectHost()) - .get( - `/v1/data/query/foo?query=${qs}&returnQuery=false&resultSourceMap=withKeyArraySelector`, - ) - .reply(200, {ms: 123, result, resultSourceMap}) + .get(`/v1/data/query/foo?query=${qs}&resultSourceMap=withKeyArraySelector`) + .reply(200, {ms: 123, query, result, resultSourceMap}) const res = await getClient({stega: {studioUrl, enabled: true}}).fetch(query, params, { stega: {