Skip to content

Commit

Permalink
feat(codegen): Allow query reponse types to be overridden through San…
Browse files Browse the repository at this point in the history
…ityQueries (#858)
  • Loading branch information
romeovs authored Jul 11, 2024
1 parent 38c440a commit c25d51a
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 29 deletions.
89 changes: 60 additions & 29 deletions src/SanityClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import type {
BaseActionOptions,
BaseMutationOptions,
ClientConfig,
ClientReturn,
FilteredResponseQueryOptions,
FirstDocumentIdMutationOptions,
FirstDocumentMutationOptions,
Expand Down Expand Up @@ -142,48 +143,61 @@ export class ObservableSanityClient {
*
* @param query - GROQ-query to perform
*/
fetch<R = Any, Q extends QueryWithoutParams = QueryWithoutParams>(
query: string,
params?: Q | QueryWithoutParams,
): Observable<R>
fetch<
R = Any,
Q extends QueryWithoutParams = QueryWithoutParams,
const G extends string = string,
>(query: G, params?: Q | QueryWithoutParams): Observable<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Optional request options
*/
fetch<R = Any, Q extends QueryWithoutParams | QueryParams = QueryParams>(
query: string,
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options?: FilteredResponseQueryOptions,
): Observable<R>
): Observable<ClientReturn<G, 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>(
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: string,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Observable<RawQueryResponse<R>>
): Observable<RawQueryResponse<ClientReturn<G, 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,
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Observable<RawQuerylessQueryResponse<R>>
fetch<R, Q>(
query: string,
): Observable<RawQuerylessQueryResponse<ClientReturn<G, R>>>
fetch<R, Q, const G extends string>(
query: G,
params?: Q,
options?: QueryOptions,
): Observable<RawQueryResponse<R> | R> {
Expand Down Expand Up @@ -808,49 +822,66 @@ export class SanityClient {
*
* @param query - GROQ-query to perform
*/
fetch<R = Any, Q extends QueryWithoutParams = QueryWithoutParams>(
query: string,
params?: Q | QueryWithoutParams,
): Promise<R>
fetch<
R = Any,
Q extends QueryWithoutParams = QueryWithoutParams,
const G extends string = string,
>(query: G, params?: Q | QueryWithoutParams): Promise<ClientReturn<G, R>>
/**
* Perform a GROQ-query against the configured dataset.
*
* @param query - GROQ-query to perform
* @param params - Optional query parameters
* @param options - Optional request options
*/
fetch<R = Any, Q extends QueryWithoutParams | QueryParams = QueryParams>(
query: string,
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options?: FilteredResponseQueryOptions,
): Promise<R>
): Promise<ClientReturn<G, 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,
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseQueryOptions,
): Promise<RawQueryResponse<R>>
): Promise<RawQueryResponse<ClientReturn<G, 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,
fetch<
R = Any,
Q extends QueryWithoutParams | QueryParams = QueryParams,
const G extends string = string,
>(
query: G,
params: Q extends QueryWithoutParams ? QueryWithoutParams : Q,
options: UnfilteredResponseWithoutQuery,
): Promise<RawQuerylessQueryResponse<R>>
fetch<R, Q>(query: string, params?: Q, options?: QueryOptions): Promise<RawQueryResponse<R> | R> {
): Promise<RawQuerylessQueryResponse<ClientReturn<G, R>>>
fetch<R, Q, const G extends string>(
query: G,
params?: Q,
options?: QueryOptions,
): Promise<RawQueryResponse<ClientReturn<G, R>> | ClientReturn<G, R>> {
return lastValueFrom(
dataMethods._fetch<R, Q>(
dataMethods._fetch<ClientReturn<G, R>, Q>(
this,
this.#httpRequest,
this.#clientConfig.stega,
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,15 @@ export interface LiveEventMessage {
tags: SyncTag[]
}

/** @public */
export interface SanityQueries {}

/** @public */
export type ClientReturn<
GroqString extends string,
Fallback = Any,
> = GroqString extends keyof SanityQueries ? SanityQueries[GroqString] : Fallback

export type {
ContentSourceMapParsedPath,
ContentSourceMapParsedPathKeyedSegment,
Expand Down
65 changes: 65 additions & 0 deletions test/codegen/client.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {createClient, type RawQueryResponse} from '@sanity/client'
import {describe, expectTypeOf, test} from 'vitest'

type FooResult = {
bar: number
}

// This would normally be generated by @sanity/codegen
declare module '@sanity/client' {
export interface SanityQueries {
"*[_type == 'foo']": FooResult
}
}

describe('client.fetch', () => {
const client = createClient({})

describe('without params', () => {
test('known query type', async () => {
const resp = await client.fetch("*[_type == 'foo']")
expectTypeOf(resp).toMatchTypeOf<FooResult>()
})

test('ad-hoc query type', async () => {
const resp = await client.fetch("*[_type == 'bar']")
expectTypeOf(resp).toMatchTypeOf<any>()
})

test('ad-hoc query with a custom type', async () => {
type Result = {bar: string}
const resp = await client.fetch<Result>("*[_type == 'bar']")
expectTypeOf(resp).toMatchTypeOf<Result>()
})

test('known query type, but overriden with ad-hoc type', async () => {
type Result = {bar: string}
const resp = await client.fetch<Result>("*[_type == 'foo']")
expectTypeOf(resp).toMatchTypeOf<Result>()
})
})

describe('unfiltered response', () => {
test('known query type', async () => {
const resp = await client.fetch("*[_type == 'foo']", {}, {filterResponse: false})
expectTypeOf(resp).toMatchTypeOf<RawQueryResponse<FooResult>>()
})

test('ad-hoc query type', async () => {
const resp = await client.fetch("*[_type == 'bar']", {}, {filterResponse: false})
expectTypeOf(resp).toMatchTypeOf<RawQueryResponse<any>>()
})

test('ad-hoc query with a custom type', async () => {
type Result = {bar: string}
const resp = await client.fetch<Result>("*[_type == 'bar']", {}, {filterResponse: false})
expectTypeOf(resp).toMatchTypeOf<RawQueryResponse<Result>>()
})

test('known query type, but overriden with ad-hoc type', async () => {
type Result = {bar: string}
const resp = await client.fetch<Result>("*[_type == 'foo']", {}, {filterResponse: false})
expectTypeOf(resp).toMatchTypeOf<RawQueryResponse<Result>>()
})
})
})

0 comments on commit c25d51a

Please sign in to comment.