Open kupe517 opened 2 months ago
Hi @kupe517 ! Thanks for reporting. I'm afraid I'm not able to reproduce, but I'm also using a pretty simple object in my array along with a reference to two possible document types. Would you mind passing along the definition of customPromo
-- maybe there are some clues there that will help us reproduce this error.
@cngonzalez Here is customPromo
along with the other objects that appear in it:
export default {
name: 'customPromo',
title: 'Custom Promo',
type: 'object',
fields: [
{
name: 'image',
title: 'Image',
type: 'imageWithAltAndMask',
validation: (Rule) => Rule.required(),
},
{
name: 'title',
title: 'Title',
type: 'string',
validation: (Rule) => Rule.required(),
},
{
name: 'subtitle',
title: 'Subtitle',
type: 'string',
},
{
name: 'price',
title: 'Price',
type: 'number',
},
{
name: 'duration',
title: 'Duration',
type: 'string',
options: {
list: [
{ title: 'Monthly', value: 'month' },
{ title: 'Yearly', value: 'year' },
{ title: 'Weekly', value: 'week' },
{ title: 'Daily', value: 'day' },
],
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (!value && parent?.price) {
return 'Required';
}
return true;
}),
},
{
name: 'blurb',
title: 'Blurb',
type: 'basicBlock',
},
{
name: 'footer',
title: 'Footer',
type: 'basicBlock',
},
{
name: 'includeCta',
title: 'Include CTA?',
type: 'boolean',
},
{
name: 'cta',
title: 'CTA',
type: 'link',
hidden: ({ parent }) => !parent?.includeCta,
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (parent?.includeCta && !value) {
return 'CTA information is required.';
}
if (value && !value.label) {
return 'CTA label is required.';
}
if (value && !value.internalLink && !value.externalLink) {
return 'Either an internal or external link is required.';
}
return true;
}),
},
],
preview: {
select: {
title: 'title',
media: 'image.image',
},
prepare({ title, media }) {
return {
title: title || '',
subtitle: 'Custom Promo',
media: media,
};
},
},
};
export default {
name: 'imageWithAltAndMask',
title: 'Image With Alt and Mask',
type: 'object',
fields: [
{
name: 'image',
title: 'Image',
type: 'image',
options: {
hotspot: true,
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (value && value.asset && value.asset._ref) {
return true;
} else {
return 'Please select an image';
}
}),
},
{
name: 'alt',
type: 'string',
title: 'Alt Text',
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (parent && parent.alt) {
return true;
} else {
return 'Please provide alt text';
}
}),
options: {
isHighlighted: true,
},
},
{
name: 'mask',
title: 'Image Mask',
type: 'string',
options: {
list: [
{ title: 'Square', value: 'square' },
{ title: 'Circle', value: 'circle' },
{ title: 'Blob', value: 'blob' },
{ title: 'Shield', value: 'shield' },
{ title: 'No Mask', value: 'no-mask' },
],
layout: 'dropdown',
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (parent && parent.mask) {
return true;
} else {
return 'Please select an image mask';
}
}),
},
],
};
import { LinkIcon, DocumentIcon } from '@sanity/icons';
export default {
title: 'Basic Block',
name: 'basicBlock',
type: 'array',
of: [
{
title: 'Block',
type: 'block',
styles: [{ title: 'Normal', value: 'normal' }],
lists: [
{ title: 'Bullet', value: 'bullet' },
{ title: 'Numbered', value: 'number' },
],
marks: {
decorators: [
{ title: 'Strong', value: 'strong' },
{ title: 'Emphasis', value: 'em' },
],
annotations: [
{
name: 'internalLink',
icon: DocumentIcon,
type: 'object',
title: 'Internal Link',
fields: [
{
name: 'reference',
type: 'reference',
title: 'Reference',
to: [{ type: 'page' }],
validation: (Rule) => Rule.required(),
},
],
},
{
name: 'externalLink',
type: 'object',
title: 'External Link',
icon: LinkIcon,
fields: [
{
name: 'url',
type: 'url',
title: 'URL',
validation: (Rule) => Rule.required(),
},
],
},
],
},
},
],
};
Thank you for the follow up @kupe517
I tried to reproduce this on version 3.52.2
with the schemas you sent us, but I could not. The problem does not seem to be a mix of a reference and an object.
I had to comment out a few types which were omitted, so perhaps the issue is in those types. I had do modify your schema to avoid missing types event
, exhibit
, page
, link
{
name: 'featuredEntries',
type: 'array',
title: 'Featured Entries',
of: [
{
type: 'reference',
to: [{ type: 'program' },
//{ type: 'event' }, { type: 'exhibit' }, { type: 'page' }
],
},
{
type: 'customPromo',
},
],
validation: (Rule) => Rule.required().min(2).max(3),
},
Full schema definitions I tested with below
import { defineType } from "sanity"
const customPromo = defineType({
name: 'customPromo',
title: 'Custom Promo',
type: 'object',
fields: [
{
name: 'image',
title: 'Image',
type: 'imageWithAltAndMask',
validation: (Rule) => Rule.required(),
},
{
name: 'title',
title: 'Title',
type: 'string',
validation: (Rule) => Rule.required(),
},
{
name: 'subtitle',
title: 'Subtitle',
type: 'string',
},
{
name: 'price',
title: 'Price',
type: 'number',
},
{
name: 'duration',
title: 'Duration',
type: 'string',
options: {
list: [
{ title: 'Monthly', value: 'month' },
{ title: 'Yearly', value: 'year' },
{ title: 'Weekly', value: 'week' },
{ title: 'Daily', value: 'day' },
],
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (!value && parent?.price) {
return 'Required';
}
return true;
}),
},
{
name: 'blurb',
title: 'Blurb',
type: 'basicBlock',
},
{
name: 'footer',
title: 'Footer',
type: 'basicBlock',
},
{
name: 'includeCta',
title: 'Include CTA?',
type: 'boolean',
},
//{
// name: 'cta',
// title: 'CTA',
// type: 'link',
// hidden: ({ parent }) => !parent?.includeCta,
// validation: (Rule) =>
// Rule.custom((value, { parent }) => {
// if (parent?.includeCta && !value) {
// return 'CTA information is required.';
// }
// if (value && !value.label) {
// return 'CTA label is required.';
// }
// if (value && !value.internalLink && !value.externalLink) {
// return 'Either an internal or external link is required.';
// }
// return true;
// }),
//},
],
preview: {
select: {
title: 'title',
media: 'image.image',
},
prepare({ title, media }) {
return {
title: title || '',
subtitle: 'Custom Promo',
media: media,
};
},
},
})
const program = defineType({
name: "program",
type: "document",
fields: [
{
type: "string",
name: "title"
}
]
})
const testDoc = defineType({
name: "testDoc",
type: "document",
fields: [
{
name: 'featuredEntries',
type: 'array',
title: 'Featured Entries',
of: [
{
type: 'reference',
to: [{ type: 'program' },
//{ type: 'event' }, { type: 'exhibit' }, { type: 'page' }
],
},
{
type: 'customPromo',
},
],
validation: (Rule) => Rule.required().min(2).max(3),
},
]
})
import { LinkIcon, DocumentIcon } from '@sanity/icons';
const basicBlock = defineType({
title: 'Basic Block',
name: 'basicBlock',
type: 'array',
of: [
{
title: 'Block',
type: 'block',
styles: [{ title: 'Normal', value: 'normal' }],
lists: [
{ title: 'Bullet', value: 'bullet' },
{ title: 'Numbered', value: 'number' },
],
marks: {
decorators: [
{ title: 'Strong', value: 'strong' },
{ title: 'Emphasis', value: 'em' },
],
annotations: [
{
name: 'internalLink',
icon: DocumentIcon,
type: 'object',
title: 'Internal Link',
fields: [
{
name: 'reference',
type: 'reference',
title: 'Reference',
//to: [{ type: 'page' }],
to: [{ type: 'program' }],
validation: (Rule) => Rule.required(),
},
],
},
{
name: 'externalLink',
type: 'object',
title: 'External Link',
icon: LinkIcon,
fields: [
{
name: 'url',
type: 'url',
title: 'URL',
validation: (Rule) => Rule.required(),
},
],
},
],
},
},
],
})
const imageWithAltAndMask = defineType({
name: 'imageWithAltAndMask',
title: 'Image With Alt and Mask',
type: 'object',
fields: [
{
name: 'image',
title: 'Image',
type: 'image',
options: {
hotspot: true,
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (value && value.asset && value.asset._ref) {
return true;
} else {
return 'Please select an image';
}
}),
},
{
name: 'alt',
type: 'string',
title: 'Alt Text',
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (parent && parent.alt) {
return true;
} else {
return 'Please provide alt text';
}
}),
options: {
isHighlighted: true,
},
},
{
name: 'mask',
title: 'Image Mask',
type: 'string',
options: {
list: [
{ title: 'Square', value: 'square' },
{ title: 'Circle', value: 'circle' },
{ title: 'Blob', value: 'blob' },
{ title: 'Shield', value: 'shield' },
{ title: 'No Mask', value: 'no-mask' },
],
layout: 'dropdown',
},
validation: (Rule) =>
Rule.custom((value, { parent }) => {
if (parent && parent.mask) {
return true;
} else {
return 'Please select an image mask';
}
}),
},
],
})
export const schemaTypes = [program, testDoc, customPromo, basicBlock, imageWithAltAndMask]
@runeb That was an interesting discovery you found. In further debugging I discovered that the graphQL will build if there is only a single item in the to
field for references, like the example you tested. As soon as I add an additional item into the array I get the same error.
To help you further test this, here is a simple person
schema that you can add and then include in the to
array for testing:
import { IoPersonAddOutline as icon } from 'react-icons/io5';
export default {
name: 'person',
title: 'Person',
type: 'document',
icon,
fields: [
{
name: 'firstName',
title: 'First Name',
type: 'string',
validation: (Rule) => Rule.required(),
},
{
name: 'lastName',
title: 'Last Name',
type: 'string',
validation: (Rule) => Rule.required(),
},
],
preview: {
select: {
firstName: 'firstName',
lastName: 'lastName',
},
prepare({ firstName, lastName }) {
return {
title: firstName,
subtitle: lastName,
};
},
},
};
{
name: 'featuredEntries',
type: 'array',
title: 'Featured Entries',
of: [
{
type: 'reference',
to: [{ type: 'program' }, { type: 'person' }],
},
{
type: 'customPromo',
},
],
},
If you find a security vulnerability, do NOT open an issue. Email security@sanity.io instead.
Describe the bug
When using an array which combines both references and an object there is an error that occurs which prevents deploying the graphql via
sanity graphql deploy
command. The error is:TypeError: Cannot read properties of undefined (reading 'name')
.To Reproduce
Steps to reproduce the behavior:
array
.of
array include an object which is of typereference
. Create another object which is of atype
that references an object.sanity graphql deploy
Expected behavior
The graphql should deploy with no issue. This setup is documented here.
Which versions of Sanity are you using?
@sanity/cli (global) 3.30.0 (latest: 3.49.0) @sanity/color-input 3.1.1 (up to date) @sanity/document-internationalization 3.0.0 (up to date) @sanity/eslint-config-studio 4.0.0 (up to date) @sanity/vision 3.49.0 (up to date) sanity 3.49.0 (up to date)
What operating system are you using? MacOS Sonoma 14.5
Which versions of Node.js / npm are you running?
10.2.3 v18.19.0