saiichihashimoto / sanity-typed

Completing sanity's developer experience with typescript (and more)!
MIT License
148 stars 7 forks source link

Issue with null value in referenced document #702

Open trulymittal opened 4 months ago

trulymittal commented 4 months ago
  1. Though I am getting the correct fields in the referenced document, but all the values are null type instead being string | nulltype.
  2. Using groq asimport groq from 'groq' using the GROQ tagged template literal, I am getting a response as Promise<never> instead of being typed, Is this the intended behavior
saiichihashimoto commented 4 months ago
  1. Can you provide the schema or query for what you're talking about?
  2. I hadn't even considered the groq template literal, will need to do that!
trulymittal commented 3 months ago

Sure here it is:

This is the site settings schema

import { Settings2Icon } from 'lucide-react'
// import { defineField, defineType } from 'sanity'
import { defineField, defineType } from '@sanity-typed/types'

export const siteSettingsType = defineType({
  name: 'siteSettings',
  title: 'Site settings',
  type: 'document',
  icon: Settings2Icon,
  groups: [
    {
      name: 'general',
      title: 'General',
    },
    {
      name: 'seo',
      title: 'Global SEO',
    },
    {
      name: 'assistant',
      title: 'AI assistant',
    },
  ],
  fields: [
    defineField({
      name: 'title',
      type: 'string',
      validation: (Rule) => Rule.required(),
    }),
    defineField({
      name: 'description',
      type: 'text',
      rows: 5,
    }),
    defineField({
      title: 'AI assistant',
      name: 'assistant',
      type: 'reference',
      to: [{ type: 'assistant' as const }],
      group: ['assistant'],
    }),
    defineField({
      title: 'SEO Title',
      name: 'seoTitle',
      type: 'string',
      group: 'seo',
    }),
    defineField({
      title: 'SEO Meta description',
      name: 'seoMetaDescription',
      type: 'text',
      rows: 5,
      group: 'seo',
    }),
    defineField({
      title: 'SEO Meta image',
      name: 'seoMetaImage',
      type: 'image',
      options: {
        hotspot: true,
      },
      group: 'seo',
    }),
  ],
  preview: {
    select: {
      title: 'title',
      subtitle: 'instructions',
    },
  },
})

the assistant schema is

import { BotIcon } from 'lucide-react'
// import { defineField, defineType } from 'sanity'
import { defineField, defineType } from '@sanity-typed/types'

export const assistantType = defineType({
  name: 'assistant',
  title: 'AI Assistant',
  type: 'document',
  icon: BotIcon,
  groups: [
    {
      name: 'advanced',
      title: 'Advanced',
    },
    {
      name: 'persona',
      title: 'Persona',
    },
  ],
  fields: [
    defineField({
      name: 'title',
      type: 'string',
    }),
    defineField({
      name: 'model',
      type: 'string',
      options: {
        list: [
          { title: 'GPT-3.5-TURBO', value: 'gpt-3.5-turbo' },
          { title: 'GPT-4-TURBO-PREVIEW', value: 'gpt-4-turbo-preview' },
          { title: 'GPT-4', value: 'gpt-4' },
        ],
      },
      initialValue: 'gpt-3.5-turbo',
    }),
    defineField({
      name: 'instructions',
      type: 'text',
      rows: 5,
      group: 'persona',
    }),
    defineField({
      name: 'temperature',
      type: 'number',
      initialValue: 0.2,
      validation: (rule) => rule.required().min(0).max(1).precision(1),
      group: 'advanced',
    }),
    {
      title: 'Functions',
      name: 'functions',
      type: 'array',
      of: [
        {
          type: 'string',
          options: {
            list: [
              { title: 'Google places', value: 'google-places-api' },
              { title: 'Google Directions', value: 'google-directions-api' },
              { title: 'Tavily search', value: 'tavily-search' },
              { title: 'Exa search', value: 'exa-search' },
              { title: 'Search API', value: 'search-api' }
            ],
          },
        },
      ],
      group: 'advanced',
    },
  ],
  preview: {
    select: {
      title: 'title',
      subtitle: 'model',
    },
  },
})

The query I am making is

export const ASSISTANT_QUERY = `*[_type == "siteSettings" && _id == "siteSettings"][0]{
  assistant -> {
    temperature,
    model,
    functions,
    instructions
  }
}`

Client defined as

import { createClient } from '@sanity-typed/client'

import { apiVersion, dataset, projectId } from '~/sanity/projectDetails'

import type { SanityValues } from 'sanity.config'

export const client = createClient<SanityValues>({
  projectId,
  dataset,
  apiVersion,
  useCdn: true,
  perspective: 'published',
})

Sanity.config.ts

import { visionTool } from '@sanity/vision'
// import { defineConfig } from 'sanity'
import { InferSchemaValues, defineConfig } from '@sanity-typed/types'
import { structureTool } from 'sanity/structure'

import { projectDetails } from '~/sanity/projectDetails'
import schema from '~/sanity/schema'
import { defaultDocumentNode, structure } from '~/sanity/structure'

export const config = defineConfig({
  ...projectDetails(),
  name: 'sanity-remix',
  title: 'Sanity Remix',
  plugins: [
    structureTool({
      structure: structure,
      defaultDocumentNode: defaultDocumentNode,
    }),
    visionTool(),
  ],
  basePath: `/studio`,
  schema: {
    types: schema,
  },
})

export type SanityValues = InferSchemaValues<typeof config>

Now when making the query as:

import { client } from '~/sanity/client'
import { ASSISTANT_QUERY } from '~/sanity/queries'

export const getCurrentAssistant = () => client.fetch(ASSISTANT_QUERY)

The return type is defined as:

const getCurrentAssistant: () => Promise<{
    assistant: {
        temperature: null;
        model: null;
        functions: null;
        instructions: null;
    };
}>

Which is not the correct return type, though type definitions are there, but individual fields are not...

For 2, when making the query as

import groq from 'groq'

export const ASSISTANT_QUERY = groq`*[_type == "siteSettings" && _id == "siteSettings"][0]{
  assistant -> {
    temperature,
    model,
    functions,
    instructions
  }
}`

The return type is not even typed, as you said you haven't factored this in, but just for clarity, the return type is:

const getCurrentAssistant: () => Promise<never>