stipsan / groqz

(experimental) Transforms GROQ strings to zod schemas in your TypeScript codebase.

Home Page:https://groqz-docs.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Explore generating a `d.ts` file with the cli

stipsan opened this issue · comments

Instead of having to append as import('./file.typegen') to each query, it would be super neat if a d.ts were generated.

Just 1 file the cli writes to.

The d.ts could look like:

declare module 'groqz' {
  interface TypedQueries {
    `*[_type == "author" && defined(name)]{_type,name, birth}`: z.ZodType<
	  {
	    _type: 'author'
	    name: string
        birth: Date | null
	  }[]
	>,
    `*[_type == "$type"]{_type, ${string}}`: z.ZodType<
	  {
	    _type: 'author' | 'book' | 'sanity.imageAsset'
	    [key: string]: import('groqz').Json
	  }[]
	>
  }
}

For this to work, the typings for groqz needs to use this interface in the typings for the groq function:

import { json as schema } from '@groqz/json'

import type { ParsedQuery } from './types'

export interface TypedQueries {
 // Declared by typegen by using TS declaration merging
}

export function groq<T = TemplateStringsArray>(strings: T): T extends keyof TypedQueries ? TypedQueries[T] : ParsedQuery<typeof schema>
export function groq(
  strings: TemplateStringsArray,
  // @TODO change the typing to disallow arguments, as they're not supported
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  ...keys: any[]
): ParsedQuery<typeof schema>

And now the typings here should "just work" in both the IDE and when running tsc --noEmit:

import {groq} from 'groqz'

const {query, schema} = groq`*[_type == "author" && defined(name)]{_type,name, birth}`
// query is now `*[_type == "author" && defined(name)]{_type,name, birth}` instead of string
// and schema is `z.ZodType` instead of the `import('groqz').Json` fallback