Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(codegen): generate SanityQueries interface in @sanity/codegen #7304

Merged
merged 1 commit into from
Aug 3, 2024

Conversation

stipsan
Copy link
Member

@stipsan stipsan commented Aug 2, 2024

Description

This PR is just forwarding #6997 by @romeovs (with help from @sgulseth ), so that we can run all the CI testing flows that otherwise are skipped/fail on PRs from forked branches.

Check #6997 for all the deets, the gist of it is that it allows typegen that are much more ✨ magical ✨ and easier to use.

Today typegen requires you to instrument your client.fetch calls with the generated query response:

import {createClient} from '@sanity/client'
import groq from 'groq'
// You have to manually import from the generated `sanity.types.ts` file
import type { SettingsQueryResult } from "~/sanity.types";

const client = createClient({ /* ... */ })

const settingsQuery = groq`*[_type == "settings"][0]`

// And also manually add the type for the response to the generic slot in `client.fetch`
const settings = await client.fetch<SettingsQueryResult>(settingsQuery)

This burden compounds as the client.fetch itself might be abstracted away in higher level functions. For apps like on next it's common to define a sanityFetch function and must remember to forward the QueryResponse generic.

Now, given these requirements:

  • @sanity/client is on a recent version (v6.21.0 or later) that has the new SanityQueries interface.
  • queries are defined with the new defineQuery utility from groq instead of groq
  • @sanity/codegen is configured to generate the SanityQueries interface, it's opt-in by setting "overloadClientMethods": true in sanity-typegen.json
    Then it's far less work to use the generated typings, and the DevEx is that it "just works"✨✨
import {createClient} from '@sanity/client'
// You need to import `defineQuery` instead of `groq`
import {defineQuery} from 'groq'

const client = createClient({ /* ... */ })

// It's used as a function instead of a tagged template literal
const settingsQuery = defineQuery(`*[_type == "settings"][0]`)

// `settings` is typed, no generics needed, and it works well with custom wrapper functions that also no longer need to use generics
const settings = await client.fetch(settingsQuery)

What to review

This feature brings a lot of value, and I struggle to find a use case where you want it disabled. Should we make overloadClientMethods true by default and rather opt-out if necessary?
The only cost to using this is potentially that typegen takes longer than needed if the feature isn't used for whatever reason, AFAIK.
If someone were to update sanity on a project that already use generics with client.fetch then the generic they pass takes precedence, so it shouldn't cause conflicts with codebases that already use typegen.

Testing

I've made a canary release that can be used to e2e test in userland: npm i --save-exact [email protected].
To ensure that we don't regress any code that today rely on being able to import groq in ESM like:

import groq from 'groq'

and in CJS:

const groq = require('groq')

We added a testing suite that runtime checks these in node: https://github.com/sanity-io/sanity/tree/3b2329cf640954f308676a4b02f3fda701c65587/packages/groq/test
These tests makes us feel comfortable that we can introduce the new defineQuery utility as a named export in ESM:

import {defineQuery} from 'groq'

and CJS:

const {defineQuery} = require('groq')

You can even mix them:

import groq, {defineQuery} from 'groq'
const groq = require('groq')
const {defineQuery} = groq

const legacyQuery = groq`count(*)`
const magicQuery = defineQuery(`count(*)`)

Notes for release

It's now possible to use TypeGen without manually passing around generics into client.fetch calls 🥳
Update @sanity/client so you're on v6.21.0 or later. Add "overloadClientMethods": true to your sanity-typegen.json, and wrap your query strings in the new defineQuery utility from groq:

import {createClient} from '@sanity/client'
-import groq from 'groq'
+import {defineQuery} from 'groq'
-import type { SettingsQueryResult } from "~/sanity.types";

const client = createClient({ /* ... */ })

-const settingsQuery = groq`
+const settingsQuery = defineQuery(`
  *[_type == "settings"][0]
-`
+`)

-const settings = await client.fetch<SettingsQueryResult>(settingsQuery)
+const settings = await client.fetch(settingsQuery)

…6997)

* fix(deps): update dependency @sanity/client to ^6.21.1 (#7215)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(typegen): groq/define module with a defineQuery helper

* feat(typegen): Recognize queries that are wrapped in defineQuery calls

* feat(typegen): Add overloadClientMethods option to @sanity/codegen

* refactor(codegen): Return the typename of a generated type node so we can store it for later use

* feat(typegen): Add generateTypeMap helper to TypeGenerator

* feat(typegen): Allow codegen cli to generate the SanityQueries type map

* docs(typegen): Add docs about defineQuery to groq README

* refactor(groq): Allow defineQuery to live in the groq package

* refactor(groq): Use the correct groq import in codegen tests

* fix(codegen): Only use defineQuery when it comes from the groq package

* refactor(codegen): Avoid changing the signature for generateTypeNodeTypes

* refactor(codegen): Use typeNode to reference types in typeGenerator

* feat(codegen): Handle duplicate query strings

---------
Copy link

vercel bot commented Aug 2, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
page-building-studio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 2, 2024 2:02pm
performance-studio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 2, 2024 2:02pm
test-compiled-studio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 2, 2024 2:02pm
test-next-studio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 2, 2024 2:02pm
test-studio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 2, 2024 2:02pm
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
studio-workshop ⬜️ Ignored (Inspect) Aug 2, 2024 2:02pm

Copy link
Contributor

github-actions bot commented Aug 2, 2024

No changes to documentation

@stipsan stipsan marked this pull request as ready for review August 2, 2024 14:10
@stipsan stipsan requested review from a team as code owners August 2, 2024 14:10
@stipsan stipsan requested review from juice49 and removed request for a team August 2, 2024 14:10
Copy link
Contributor

github-actions bot commented Aug 2, 2024

Component Testing Report Updated Aug 2, 2024 2:20 PM (UTC)

File Status Duration Passed Skipped Failed
comments/CommentInput.spec.tsx ✅ Passed (Inspect) 46s 15 0 0
formBuilder/ArrayInput.spec.tsx ✅ Passed (Inspect) 9s 3 0 0
formBuilder/inputs/PortableText/Annotations.spec.tsx ✅ Passed (Inspect) 31s 6 0 0
formBuilder/inputs/PortableText/copyPaste/CopyPaste.spec.tsx ✅ Passed (Inspect) 37s 11 7 0
formBuilder/inputs/PortableText/copyPaste/CopyPasteFields.spec.tsx ✅ Passed (Inspect) 0s 0 12 0
formBuilder/inputs/PortableText/Decorators.spec.tsx ✅ Passed (Inspect) 17s 6 0 0
formBuilder/inputs/PortableText/DisableFocusAndUnset.spec.tsx ✅ Passed (Inspect) 10s 3 0 0
formBuilder/inputs/PortableText/DragAndDrop.spec.tsx ✅ Passed (Inspect) 3m 0s 0 0 0
formBuilder/inputs/PortableText/FocusTracking.spec.tsx ✅ Passed (Inspect) 44s 15 0 0
formBuilder/inputs/PortableText/Input.spec.tsx ✅ Passed (Inspect) 1m 45s 21 0 0
formBuilder/inputs/PortableText/ObjectBlock.spec.tsx ✅ Passed (Inspect) 1m 14s 18 0 0
formBuilder/inputs/PortableText/PresenceCursors.spec.tsx ✅ Passed (Inspect) 8s 3 9 0
formBuilder/inputs/PortableText/RangeDecoration.spec.tsx ✅ Passed (Inspect) 25s 9 0 0
formBuilder/inputs/PortableText/Styles.spec.tsx ✅ Passed (Inspect) 18s 6 0 0
formBuilder/inputs/PortableText/Toolbar.spec.tsx ✅ Passed (Inspect) 1m 13s 21 0 0
formBuilder/tree-editing/TreeEditing.spec.tsx ✅ Passed (Inspect) 1m 46s 30 0 0
formBuilder/tree-editing/TreeEditingNestedObjects.spec.tsx ✅ Passed (Inspect) 20s 3 0 0

@stipsan stipsan added this pull request to the merge queue Aug 3, 2024
Merged via the queue into next with commit 886ab25 Aug 3, 2024
42 checks passed
@stipsan stipsan deleted the feat/define-groq-query-typemap branch August 3, 2024 08:03
cngonzalez pushed a commit that referenced this pull request Aug 20, 2024
…6997) (#7304)

* fix(deps): update dependency @sanity/client to ^6.21.1 (#7215)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* feat(typegen): groq/define module with a defineQuery helper

* feat(typegen): Recognize queries that are wrapped in defineQuery calls

* feat(typegen): Add overloadClientMethods option to @sanity/codegen

* refactor(codegen): Return the typename of a generated type node so we can store it for later use

* feat(typegen): Add generateTypeMap helper to TypeGenerator

* feat(typegen): Allow codegen cli to generate the SanityQueries type map

* docs(typegen): Add docs about defineQuery to groq README

* refactor(groq): Allow defineQuery to live in the groq package

* refactor(groq): Use the correct groq import in codegen tests

* fix(codegen): Only use defineQuery when it comes from the groq package

* refactor(codegen): Avoid changing the signature for generateTypeNodeTypes

* refactor(codegen): Use typeNode to reference types in typeGenerator

* feat(codegen): Handle duplicate query strings

---------

Co-authored-by: Romeo Van Snick <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants