From b9441437778b07f361a14575f29fece53ffead31 Mon Sep 17 00:00:00 2001 From: Cody Olsen <81981+stipsan@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:52:45 +0200 Subject: [PATCH] examples: Improve TypeGen in Sanity Example (#68580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses the improved TypeGen just released in `sanity` [v3.53.0](https://github.com/sanity-io/sanity/releases/tag/v3.53.0) 🥳 --- examples/cms-sanity/app/(blog)/layout.tsx | 7 ++-- .../cms-sanity/app/(blog)/more-stories.tsx | 6 +--- .../app/(blog)/posts/[slug]/page.tsx | 30 ++++++----------- examples/cms-sanity/package.json | 11 ++++--- examples/cms-sanity/sanity-typegen.json | 1 + examples/cms-sanity/sanity.types.ts | 26 +++++++++++---- examples/cms-sanity/sanity/lib/fetch.ts | 8 ++--- examples/cms-sanity/sanity/lib/queries.ts | 32 +++++++++++-------- 8 files changed, 62 insertions(+), 59 deletions(-) create mode 100644 examples/cms-sanity/sanity-typegen.json diff --git a/examples/cms-sanity/app/(blog)/layout.tsx b/examples/cms-sanity/app/(blog)/layout.tsx index 7d934be6368c7..6a23f51370b07 100644 --- a/examples/cms-sanity/app/(blog)/layout.tsx +++ b/examples/cms-sanity/app/(blog)/layout.tsx @@ -14,14 +14,13 @@ import { Suspense } from "react"; import AlertBanner from "./alert-banner"; import PortableText from "./portable-text"; -import type { SettingsQueryResult } from "@/sanity.types"; import * as demo from "@/sanity/lib/demo"; import { sanityFetch } from "@/sanity/lib/fetch"; import { settingsQuery } from "@/sanity/lib/queries"; import { resolveOpenGraphImage } from "@/sanity/lib/utils"; export async function generateMetadata(): Promise { - const settings = await sanityFetch({ + const settings = await sanityFetch({ query: settingsQuery, // Metadata should never contain stega stega: false, @@ -58,9 +57,7 @@ const inter = Inter({ }); async function Footer() { - const data = await sanityFetch({ - query: settingsQuery, - }); + const data = await sanityFetch({ query: settingsQuery }); const footer = data?.footer || []; return ( diff --git a/examples/cms-sanity/app/(blog)/more-stories.tsx b/examples/cms-sanity/app/(blog)/more-stories.tsx index eda89220fa501..ea7a993ae42fd 100644 --- a/examples/cms-sanity/app/(blog)/more-stories.tsx +++ b/examples/cms-sanity/app/(blog)/more-stories.tsx @@ -4,7 +4,6 @@ import Avatar from "./avatar"; import CoverImage from "./cover-image"; import DateComponent from "./date"; -import type { MoreStoriesQueryResult } from "@/sanity.types"; import { sanityFetch } from "@/sanity/lib/fetch"; import { moreStoriesQuery } from "@/sanity/lib/queries"; @@ -12,10 +11,7 @@ export default async function MoreStories(params: { skip: string; limit: number; }) { - const data = await sanityFetch({ - query: moreStoriesQuery, - params, - }); + const data = await sanityFetch({ query: moreStoriesQuery, params }); return ( <> diff --git a/examples/cms-sanity/app/(blog)/posts/[slug]/page.tsx b/examples/cms-sanity/app/(blog)/posts/[slug]/page.tsx index 452f0447ccc86..397fb23e78dc0 100644 --- a/examples/cms-sanity/app/(blog)/posts/[slug]/page.tsx +++ b/examples/cms-sanity/app/(blog)/posts/[slug]/page.tsx @@ -1,5 +1,6 @@ +import { defineQuery } from "groq"; import type { Metadata, ResolvingMetadata } from "next"; -import { groq, type PortableTextBlock } from "next-sanity"; +import { type PortableTextBlock } from "next-sanity"; import Link from "next/link"; import { notFound } from "next/navigation"; import { Suspense } from "react"; @@ -10,11 +11,6 @@ import DateComponent from "../../date"; import MoreStories from "../../more-stories"; import PortableText from "../../portable-text"; -import type { - PostQueryResult, - PostSlugsResult, - SettingsQueryResult, -} from "@/sanity.types"; import * as demo from "@/sanity/lib/demo"; import { sanityFetch } from "@/sanity/lib/fetch"; import { postQuery, settingsQuery } from "@/sanity/lib/queries"; @@ -24,26 +20,23 @@ type Props = { params: { slug: string }; }; -const postSlugs = groq`*[_type == "post"]{slug}`; +const postSlugs = defineQuery( + `*[_type == "post" && defined(slug.current)]{"slug": slug.current}`, +); export async function generateStaticParams() { - const params = await sanityFetch({ + return await sanityFetch({ query: postSlugs, perspective: "published", stega: false, }); - return params.map(({ slug }) => ({ slug: slug?.current })); } export async function generateMetadata( { params }: Props, parent: ResolvingMetadata, ): Promise { - const post = await sanityFetch({ - query: postQuery, - params, - stega: false, - }); + const post = await sanityFetch({ query: postQuery, params, stega: false }); const previousImages = (await parent).openGraph?.images || []; const ogImage = resolveOpenGraphImage(post?.coverImage); @@ -59,13 +52,8 @@ export async function generateMetadata( export default async function PostPage({ params }: Props) { const [post, settings] = await Promise.all([ - sanityFetch({ - query: postQuery, - params, - }), - sanityFetch({ - query: settingsQuery, - }), + sanityFetch({ query: postQuery, params }), + sanityFetch({ query: settingsQuery }), ]); if (!post?._id) { diff --git a/examples/cms-sanity/package.json b/examples/cms-sanity/package.json index 4c428e8d241b5..15e03ccf69628 100644 --- a/examples/cms-sanity/package.json +++ b/examples/cms-sanity/package.json @@ -16,21 +16,22 @@ "@sanity/assist": "^3.0.5", "@sanity/icons": "^3.3.1", "@sanity/image-url": "^1.0.2", - "@sanity/preview-url-secret": "^1.6.18", - "@sanity/vision": "^3.52.4", + "@sanity/preview-url-secret": "^1.6.19", + "@sanity/vision": "^3.53.0", "@tailwindcss/typography": "^0.5.13", "@types/node": "^20.14.13", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@vercel/speed-insights": "^1.0.12", - "autoprefixer": "^10.4.19", + "autoprefixer": "^10.4.20", "date-fns": "^3.6.0", + "groq": "^3.53.0", "next": "^14.2.5", "next-sanity": "^9.4.3", - "postcss": "^8.4.40", + "postcss": "^8.4.41", "react": "^18.3.1", "react-dom": "^18.3.1", - "sanity": "^3.52.4", + "sanity": "^3.53.0", "sanity-plugin-asset-source-unsplash": "^3.0.1", "server-only": "^0.0.1", "styled-components": "^6.1.12", diff --git a/examples/cms-sanity/sanity-typegen.json b/examples/cms-sanity/sanity-typegen.json new file mode 100644 index 0000000000000..f178d69539f71 --- /dev/null +++ b/examples/cms-sanity/sanity-typegen.json @@ -0,0 +1 @@ +{ "overloadClientMethods": true } diff --git a/examples/cms-sanity/sanity.types.ts b/examples/cms-sanity/sanity.types.ts index 16bfd1b900f48..c27f9d02eb9ac 100644 --- a/examples/cms-sanity/sanity.types.ts +++ b/examples/cms-sanity/sanity.types.ts @@ -482,7 +482,7 @@ export type SettingsQueryResult = { }; } | null; // Variable: heroQuery -// Query: *[_type == "post" && defined(slug.current)] | order(date desc, _updatedAt desc) [0] { content, _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture},} +// Query: *[_type == "post" && defined(slug.current)] | order(date desc, _updatedAt desc) [0] { content, _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture}, } export type HeroQueryResult = { content: Array<{ children?: Array<{ @@ -537,7 +537,7 @@ export type HeroQueryResult = { } | null; } | null; // Variable: moreStoriesQuery -// Query: *[_type == "post" && _id != $skip && defined(slug.current)] | order(date desc, _updatedAt desc) [0...$limit] { _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture},} +// Query: *[_type == "post" && _id != $skip && defined(slug.current)] | order(date desc, _updatedAt desc) [0...$limit] { _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture}, } export type MoreStoriesQueryResult = Array<{ _id: string; status: "draft" | "published"; @@ -574,7 +574,7 @@ export type MoreStoriesQueryResult = Array<{ } | null; }>; // Variable: postQuery -// Query: *[_type == "post" && slug.current == $slug] [0] { content, _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture},} +// Query: *[_type == "post" && slug.current == $slug] [0] { content, _id, "status": select(_originalId in path("drafts.**") => "draft", "published"), "title": coalesce(title, "Untitled"), "slug": slug.current, excerpt, coverImage, "date": coalesce(date, _updatedAt), "author": author->{"name": coalesce(name, "Anonymous"), picture}, } export type PostQueryResult = { content: Array<{ children?: Array<{ @@ -628,9 +628,23 @@ export type PostQueryResult = { } | null; } | null; } | null; -// Source: ./app/(blog)/posts/[slug]/page.tsx +import "@sanity/client"; +declare module "@sanity/client" { + interface SanityQueries { + '*[_type == "settings"][0]': SettingsQueryResult; + '\n *[_type == "post" && defined(slug.current)] | order(date desc, _updatedAt desc) [0] {\n content,\n \n _id,\n "status": select(_originalId in path("drafts.**") => "draft", "published"),\n "title": coalesce(title, "Untitled"),\n "slug": slug.current,\n excerpt,\n coverImage,\n "date": coalesce(date, _updatedAt),\n "author": author->{"name": coalesce(name, "Anonymous"), picture},\n\n }\n': HeroQueryResult; + '\n *[_type == "post" && _id != $skip && defined(slug.current)] | order(date desc, _updatedAt desc) [0...$limit] {\n \n _id,\n "status": select(_originalId in path("drafts.**") => "draft", "published"),\n "title": coalesce(title, "Untitled"),\n "slug": slug.current,\n excerpt,\n coverImage,\n "date": coalesce(date, _updatedAt),\n "author": author->{"name": coalesce(name, "Anonymous"), picture},\n\n }\n': MoreStoriesQueryResult; + '\n *[_type == "post" && slug.current == $slug] [0] {\n content,\n \n _id,\n "status": select(_originalId in path("drafts.**") => "draft", "published"),\n "title": coalesce(title, "Untitled"),\n "slug": slug.current,\n excerpt,\n coverImage,\n "date": coalesce(date, _updatedAt),\n "author": author->{"name": coalesce(name, "Anonymous"), picture},\n\n }\n': PostQueryResult; + } +} // Source: ./app/(blog)/posts/[slug]/page.tsx // Variable: postSlugs -// Query: *[_type == "post"]{slug} +// Query: *[_type == "post" && defined(slug.current)]{"slug": slug.current} export type PostSlugsResult = Array<{ - slug: Slug | null; + slug: string | null; }>; +import "@sanity/client"; +declare module "@sanity/client" { + interface SanityQueries { + '*[_type == "post" && defined(slug.current)]{"slug": slug.current}': PostSlugsResult; + } +} diff --git a/examples/cms-sanity/sanity/lib/fetch.ts b/examples/cms-sanity/sanity/lib/fetch.ts index 91796e437cf50..f4d79180f5ee2 100644 --- a/examples/cms-sanity/sanity/lib/fetch.ts +++ b/examples/cms-sanity/sanity/lib/fetch.ts @@ -10,7 +10,7 @@ import { token } from "@/sanity/lib/token"; * and will also fetch from the CDN. * When using the "previewDrafts" perspective then the data is fetched from the live API and isn't cached, it will also fetch draft content that isn't published yet. */ -export async function sanityFetch({ +export async function sanityFetch({ query, params = {}, perspective = draftMode().isEnabled ? "previewDrafts" : "published", @@ -22,13 +22,13 @@ export async function sanityFetch({ stega = perspective === "previewDrafts" || process.env.VERCEL_ENV === "preview", }: { - query: string; + query: QueryString; params?: QueryParams; perspective?: Omit; stega?: boolean; }) { if (perspective === "previewDrafts") { - return client.fetch(query, params, { + return client.fetch(query, params, { stega, perspective: "previewDrafts", // The token is required to fetch draft content @@ -39,7 +39,7 @@ export async function sanityFetch({ next: { revalidate: 0 }, }); } - return client.fetch(query, params, { + return client.fetch(query, params, { stega, perspective: "published", // The `published` perspective is available on the API CDN diff --git a/examples/cms-sanity/sanity/lib/queries.ts b/examples/cms-sanity/sanity/lib/queries.ts index 955060dcbb49f..47e3f7db6f92b 100644 --- a/examples/cms-sanity/sanity/lib/queries.ts +++ b/examples/cms-sanity/sanity/lib/queries.ts @@ -1,6 +1,6 @@ -import { groq } from "next-sanity"; +import { defineQuery } from "groq"; -export const settingsQuery = groq`*[_type == "settings"][0]`; +export const settingsQuery = defineQuery(`*[_type == "settings"][0]`); const postFields = /* groq */ ` _id, @@ -13,16 +13,22 @@ const postFields = /* groq */ ` "author": author->{"name": coalesce(name, "Anonymous"), picture}, `; -export const heroQuery = groq`*[_type == "post" && defined(slug.current)] | order(date desc, _updatedAt desc) [0] { - content, - ${postFields} -}`; +export const heroQuery = defineQuery(` + *[_type == "post" && defined(slug.current)] | order(date desc, _updatedAt desc) [0] { + content, + ${postFields} + } +`); -export const moreStoriesQuery = groq`*[_type == "post" && _id != $skip && defined(slug.current)] | order(date desc, _updatedAt desc) [0...$limit] { - ${postFields} -}`; +export const moreStoriesQuery = defineQuery(` + *[_type == "post" && _id != $skip && defined(slug.current)] | order(date desc, _updatedAt desc) [0...$limit] { + ${postFields} + } +`); -export const postQuery = groq`*[_type == "post" && slug.current == $slug] [0] { - content, - ${postFields} -}`; +export const postQuery = defineQuery(` + *[_type == "post" && slug.current == $slug] [0] { + content, + ${postFields} + } +`);