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

Typegen not reading => @ correctly. #6555

Open
lorenzo-del-rosario opened this issue May 3, 2024 · 3 comments · May be fixed by sanity-io/groq-js#232
Open

Typegen not reading => @ correctly. #6555

lorenzo-del-rosario opened this issue May 3, 2024 · 3 comments · May be fixed by sanity-io/groq-js#232
Assignees
Labels
bug typegen Issues related to TypeScript types generation

Comments

@lorenzo-del-rosario
Copy link

If you find a security vulnerability, do NOT open an issue. Email [email protected] instead.

Describe the bug
I need to use a component based approach in my app.
Every page has a components field that is an array of different possible objects ((Hero | Cta)[]).
I want to resolve the image asset references for the Hero component and get the rest of my components without any modifier applied.

The generated type QUERYResult type contains only part of the queried Hero component and no types for all the other components (Cta)

To Reproduce

Steps to reproduce the behavior:

Groq query

export const HOMEPAGE_QUERY = groq`*[_type == "page" && slug.current == "homepage" && !(_id in path('drafts.**')) ]{
  title,
  slug,
  _type,
  components[] {
    _type == "hero" => { 
      _type != 'image' => @,
      "imageMobile": imageMobile.asset->{
        metadata {
          dimensions{
            width,
            height,
            aspectRatio
          }
        },
        extension,
        url,
        _id
      },
      "imageDesktop": imageDesktop.asset->{
        metadata {
          dimensions{
            width,
            height,
            aspectRatio
          }
        },
        extension,
        url,
        _id
      },
    },
    _type != 'hero' => @,
  }
}`;

Generated types (components) ✅

export type Hero = {
  _type: 'hero'
  title?: string
  subtitle?: string
  imageDesktop?: {
    asset?: {
      _ref: string
      _type: 'reference'
      _weak?: boolean
      [internalGroqTypeReferenceTo]?: 'sanity.imageAsset'
    }
    hotspot?: SanityImageHotspot
    crop?: SanityImageCrop
    _type: 'image'
  }
  imageMobile?: {
    asset?: {
      _ref: string
      _type: 'reference'
      _weak?: boolean
      [internalGroqTypeReferenceTo]?: 'sanity.imageAsset'
    }
    hotspot?: SanityImageHotspot
    crop?: SanityImageCrop
    _type: 'image'
  }
}

export type Cta = {
  _type: 'cta'
  title?: string
  buttons?: Array<
    {
      _key: string
    } & Button
  >
}

export type Button = {
  _type: 'button'
  linkLabel?: string
  linkURL?: string
}

Generated type (homepage query) ❌

export type HOMEPAGE_QUERYResult = Array<{
  title: string | null;
  slug: Slug | null;
  _type: 'page';
  components: Array<
    | {
        _key: string;
        imageMobile: {
          metadata: {
            dimensions: {
              width: number | null;
              height: number | null;
              aspectRatio: number | null;
            } | null;
          } | null;
          extension: string | null;
          url: string | null;
          _id: string;
        } | null;
        imageDesktop: {
          metadata: {
            dimensions: {
              width: number | null;
              height: number | null;
              aspectRatio: number | null;
            } | null;
          } | null;
          extension: string | null;
          url: string | null;
          _id: string;
        } | null;
      }
    | {
        _key: string;
      }
  > | null;
}>;

Expected behavior

HOMEPAGE_QUERYResult['components'] should match the value returned by the API. Hero should have a title, subtitle, _type and the resolved imageDesktop and imageDesktop references. Since all the orher components are returned in full (_type != 'hero' => @) HOMEPAGE_QUERYResult['components'] should contain all the other component types (Cta).

Screenshots

N/A

Which versions of Sanity are you using?

@sanity/cli (global) 3.40.0 (up to date)
@sanity/eslint-config-studio 4.0.0 (up to date)
@sanity/vision 3.40.0 (up to date)
sanity 3.40.0 (up to date)

What operating system are you using?

iOS

Which versions of Node.js / npm are you running?

10.2.4
v20.11.1

Additional context

The types from the schema are being generated correctly, the only issue is in the GROQ query.

Security issue?

Any security issues should be submitted directly to [email protected]. In order to determine whether you are dealing with a security issue, ask yourself these two questions:

  • Can I access something that's not mine, or something I shouldn't have access to?
  • Can I disable something for other people? If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us at [[email protected]](mailto:[email protected].
@rexxars rexxars added the typegen Issues related to TypeScript types generation label May 3, 2024
@sgulseth sgulseth removed the typegen Issues related to TypeScript types generation label May 3, 2024
@sgulseth sgulseth added bug typegen Issues related to TypeScript types generation labels May 3, 2024 — with Linear
@sgulseth
Copy link
Member

sgulseth commented May 6, 2024

Hi, thanks for reporting. I'm struggling a bit to reproduce this case. What version of the API are you using to execute the groq query? What does the schema definition for type page looks like?

@lorenzo-del-rosario
Copy link
Author

lorenzo-del-rosario commented May 6, 2024

Hi, thanks for reporting. I'm struggling a bit to reproduce this case. What version of the API are you using to execute the groq query? What does the schema definition for type page looks like?

Thank You for looking into it.

Sanity API version: 2023-03-30

The Page schema seems correct:

export type Page = {
  _id: string;
  _type: 'page';
  _createdAt: string;
  _updatedAt: string;
  _rev: string;
  title?: string;
  slug?: Slug;
  components?: Array<
    | ({
        _key: string;
      } & Hero)
    | ({
        _key: string;
      } & Cta)
  >;
};

The issue seems to happen with the narrowing of Hero and Cta when generating the type for the groq query response.

This is the Page schema definition in Sanity Studio:

import { defineField, defineType } from 'sanity';

export default defineType({
  name: 'page',
  title: 'Page',
  type: 'document',
  fields: [
    defineField({
      name: 'title',
      title: 'Title',
      type: 'string'
    }),
    defineField({
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96
      }
    }),
    defineField({
      name: 'components',
      title: 'Components',
      type: 'array',
      of: [
        {
          name: 'hero',
          type: 'hero'
        },
        {
          name: 'cta',
          type: 'cta'
        }
      ]
    })
  ],

  preview: {
    select: {
      title: 'title',
      author: 'author.name',
      media: 'mainImage'
    },
    prepare(selection) {
      const { author } = selection;
      return { ...selection, subtitle: author && `by ${author}` };
    }
  }
});

Please let me know if you'd like more information.

Or if you suggest any other way to write the query in order for the TypeGen to read it correctly for the time being.

@sgulseth
Copy link
Member

sgulseth commented May 7, 2024

Thanks! with the Page schema definition I'm able to reproduce 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug typegen Issues related to TypeScript types generation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants