diff --git a/apps/example-ssr/src/components/InternalLink.astro b/apps/example-ssr/src/components/InternalLink.astro index 96517d6..235c2d4 100644 --- a/apps/example-ssr/src/components/InternalLink.astro +++ b/apps/example-ssr/src/components/InternalLink.astro @@ -1,16 +1,15 @@ --- -import { useSanityClient } from "@sanity/astro"; +import { sanityClient } from "sanity:client"; const { node } = Astro.props; const { markDef } = node; -const client = useSanityClient(); // Only deal with posts links for this example -const destination = markDef._ref && await client.fetch( +const destination = markDef._ref && await sanityClient.fetch( `* [_type == "post" && _id == $id] {slug {current}}[0]`, { id: markDef._ref } ); -const linkText = node.children.map(c => c.text).join(' ') +const linkText = node.children.map((c: any) => c.text).join(' ') --- { diff --git a/apps/example-ssr/src/components/NewsBar.jsx b/apps/example-ssr/src/components/NewsBar.jsx new file mode 100644 index 0000000..edd4564 --- /dev/null +++ b/apps/example-ssr/src/components/NewsBar.jsx @@ -0,0 +1,29 @@ +/** + * A dynamic Newsbar that fetches content live from Sanity. + * + */ +import { useState, useEffect, useCallback } from "react"; +import { sanityClient } from "sanity:client"; + +export function NewsBar() { + const [news, setNews] = useState({ message: "Loading news…" }); + const client = sanityClient; + const getNews = useCallback(async () => { + const response = await client.fetch( + `*[_type == "sanityIoSettings"][0].banner` + ); + setNews(response || { message: "no news" }); + }, [client]); + + useEffect(() => { + getNews(); + }, [getNews]); + + return ( + + + {news.message} + + + ); +} diff --git a/apps/example-ssr/src/components/SanityImage.astro b/apps/example-ssr/src/components/SanityImage.astro index e3cf8df..fd6a548 100644 --- a/apps/example-ssr/src/components/SanityImage.astro +++ b/apps/example-ssr/src/components/SanityImage.astro @@ -1,9 +1,8 @@ --- import imageUrlBuilder from "@sanity/image-url"; -import {useSanityClient} from "@sanity/astro" +import {sanityClient} from "sanity:client" -const client = useSanityClient() -const builder = imageUrlBuilder(client) +const builder = imageUrlBuilder(sanityClient) const {node} = Astro.props const { width = 960 } = Astro.props @@ -11,11 +10,11 @@ const { width = 960 } = Astro.props // See https://www.sanity.io/docs/presenting-images for general documentation on // presenting images, and https://www.sanity.io/docs/image-url for specifics on // this builder API -const image = builder +const image = node && builder .image(node) .width(width) .fit('max') .auto('format') --- -{node.alt \ No newline at end of file +{image && {node.alt} \ No newline at end of file diff --git a/apps/example-ssr/src/layouts/Layout.astro b/apps/example-ssr/src/layouts/Layout.astro index 2142385..c9e95ba 100644 --- a/apps/example-ssr/src/layouts/Layout.astro +++ b/apps/example-ssr/src/layouts/Layout.astro @@ -1,4 +1,6 @@ ---- +--- +import { NewsBar } from '../components/NewsBar'; + interface Props { title: string; } @@ -17,6 +19,7 @@ const { title } = Astro.props; {title} + diff --git a/apps/example-ssr/src/pages/index.astro b/apps/example-ssr/src/pages/index.astro index 0254faa..5e9f5bf 100644 --- a/apps/example-ssr/src/pages/index.astro +++ b/apps/example-ssr/src/pages/index.astro @@ -1,27 +1,19 @@ --- -import { useSanityClient } from "@sanity/astro"; +import { sanityClient } from "sanity:client"; +import Layout from "../layouts/Layout.astro"; -const client = useSanityClient(); -const posts = await client.fetch(`*[_type == "post" && defined(publishedAt)] | order(publishedAt desc)`); +const posts = await sanityClient.fetch(`*[_type == "post" && defined(publishedAt)] | order(publishedAt desc)`); --- - - - - - - - Sanity.io blog - - +

Sanity.io blog

    - {posts.map((post) => ( -
  • , + {posts.map((post: any) => ( +
  • {post.title}
  • ))} - - +
+
\ No newline at end of file diff --git a/apps/example-ssr/src/pages/posts/[slug].astro b/apps/example-ssr/src/pages/posts/[slug].astro index 09138fd..ff631c6 100644 --- a/apps/example-ssr/src/pages/posts/[slug].astro +++ b/apps/example-ssr/src/pages/posts/[slug].astro @@ -1,20 +1,19 @@ --- import Layout from "../../layouts/Layout.astro"; -import { useSanityClient } from "@sanity/astro"; +import { sanityClient } from "sanity:client"; import PortableText from "../../components/PortableText.astro"; import SanityImage from "../../components/SanityImage.astro"; - const client = useSanityClient(); - const post = await client.fetch( - `*[_type == "post" && defined(publishedAt) && slug.current == $slug] | order(publishedAt desc) { - ..., - authors[]-> { - name - } - }[0]`, { - slug: Astro.params.slug, +const post = await sanityClient.fetch( + `*[_type == "post" && defined(publishedAt) && slug.current == $slug] | order(publishedAt desc) { + ..., + authors[]-> { + name } - ); + }[0]`, { + slug: Astro.params.slug, + } +); const byline = (post.authors || []).map((a:any) => a.name).join(", "); --- diff --git a/apps/example/sanity.config.ts b/apps/example/sanity.config.ts index 32d19f3..3a13dc0 100644 --- a/apps/example/sanity.config.ts +++ b/apps/example/sanity.config.ts @@ -1,11 +1,10 @@ import { visionTool } from "@sanity/vision"; import { defineConfig } from "sanity"; import { deskTool } from "sanity/desk"; +import { sanityClient } from "sanity:client"; import { schemaTypes } from "./schemas"; -export const projectId = - import.meta.env.PUBLIC_SANITY_PROJECT_ID! || "3do82whm"; -export const dataset = import.meta.env.PUBLIC_SANITY_DATASET! || "next"; +const { projectId, dataset } = sanityClient.config(); export default defineConfig({ name: "project-name", diff --git a/apps/example/src/components/InternalLink.astro b/apps/example/src/components/InternalLink.astro index 96517d6..235c2d4 100644 --- a/apps/example/src/components/InternalLink.astro +++ b/apps/example/src/components/InternalLink.astro @@ -1,16 +1,15 @@ --- -import { useSanityClient } from "@sanity/astro"; +import { sanityClient } from "sanity:client"; const { node } = Astro.props; const { markDef } = node; -const client = useSanityClient(); // Only deal with posts links for this example -const destination = markDef._ref && await client.fetch( +const destination = markDef._ref && await sanityClient.fetch( `* [_type == "post" && _id == $id] {slug {current}}[0]`, { id: markDef._ref } ); -const linkText = node.children.map(c => c.text).join(' ') +const linkText = node.children.map((c: any) => c.text).join(' ') --- { diff --git a/apps/example/src/components/NewsBar.jsx b/apps/example/src/components/NewsBar.jsx new file mode 100644 index 0000000..edd4564 --- /dev/null +++ b/apps/example/src/components/NewsBar.jsx @@ -0,0 +1,29 @@ +/** + * A dynamic Newsbar that fetches content live from Sanity. + * + */ +import { useState, useEffect, useCallback } from "react"; +import { sanityClient } from "sanity:client"; + +export function NewsBar() { + const [news, setNews] = useState({ message: "Loading news…" }); + const client = sanityClient; + const getNews = useCallback(async () => { + const response = await client.fetch( + `*[_type == "sanityIoSettings"][0].banner` + ); + setNews(response || { message: "no news" }); + }, [client]); + + useEffect(() => { + getNews(); + }, [getNews]); + + return ( + + + {news.message} + + + ); +} diff --git a/apps/example/src/components/SanityImage.astro b/apps/example/src/components/SanityImage.astro index e3cf8df..aacdb32 100644 --- a/apps/example/src/components/SanityImage.astro +++ b/apps/example/src/components/SanityImage.astro @@ -1,9 +1,9 @@ --- import imageUrlBuilder from "@sanity/image-url"; -import {useSanityClient} from "@sanity/astro" +import { sanityClient } from "sanity:client"; -const client = useSanityClient() -const builder = imageUrlBuilder(client) + +const builder = imageUrlBuilder(sanityClient) const {node} = Astro.props const { width = 960 } = Astro.props @@ -11,11 +11,11 @@ const { width = 960 } = Astro.props // See https://www.sanity.io/docs/presenting-images for general documentation on // presenting images, and https://www.sanity.io/docs/image-url for specifics on // this builder API -const image = builder +const image = node && builder .image(node) .width(width) .fit('max') .auto('format') --- -{node.alt \ No newline at end of file +{image && {node.alt} \ No newline at end of file diff --git a/apps/example/src/layouts/Layout.astro b/apps/example/src/layouts/Layout.astro index 2142385..c9e95ba 100644 --- a/apps/example/src/layouts/Layout.astro +++ b/apps/example/src/layouts/Layout.astro @@ -1,4 +1,6 @@ ---- +--- +import { NewsBar } from '../components/NewsBar'; + interface Props { title: string; } @@ -17,6 +19,7 @@ const { title } = Astro.props; {title} + diff --git a/apps/example/src/pages/index.astro b/apps/example/src/pages/index.astro index 22f7968..48f5d13 100644 --- a/apps/example/src/pages/index.astro +++ b/apps/example/src/pages/index.astro @@ -1,27 +1,19 @@ --- -import { useSanityClient } from "@sanity/astro"; +import {sanityClient} from "sanity:client"; +import Layout from "../layouts/Layout.astro"; -const client = useSanityClient(); -const posts = await client.fetch(`*[_type == "post" && defined(publishedAt)] | order(publishedAt desc)`); +const posts = await sanityClient.fetch(`*[_type == "post" && defined(publishedAt)] | order(publishedAt desc)`); --- - - - - - - - Sanity.io blog - - +

Sanity.io blog

+
diff --git a/apps/example/src/pages/posts/[slug].astro b/apps/example/src/pages/posts/[slug].astro index 48928a3..75f202d 100644 --- a/apps/example/src/pages/posts/[slug].astro +++ b/apps/example/src/pages/posts/[slug].astro @@ -1,12 +1,11 @@ --- +import { sanityClient } from "sanity:client"; import Layout from "../../layouts/Layout.astro"; -import { useSanityClient } from "@sanity/astro"; import PortableText from "../../components/PortableText.astro"; import SanityImage from "../../components/SanityImage.astro"; export async function getStaticPaths() { - const client = useSanityClient(); - const posts = await client.fetch( + const posts = await sanityClient.fetch( `*[_type == "post" && defined(publishedAt)] | order(publishedAt desc) { ..., authors[]-> { diff --git a/packages/sanity-astro/README.md b/packages/sanity-astro/README.md index 26e4772..d914c7b 100644 --- a/packages/sanity-astro/README.md +++ b/packages/sanity-astro/README.md @@ -50,15 +50,14 @@ export default defineConfig({ }); ``` -This enables the use of `useSanityClient()` in your template files. For example: +This enables the use of `sanityClient` in your template files. For example: ```mdx --- // /blog/index.astro -import { useSanityClient } from "@sanity/astro"; +import { sanityClient } from "sanity:client"; -const client = useSanityClient(); -const posts = await client.fetch(`*[_type == "post" && defined(slug)] | order(publishedAt desc)`); +const posts = await sanityClient.fetch(`*[_type == "post" && defined(slug)] | order(publishedAt desc)`); ---

Blog

@@ -73,7 +72,7 @@ const posts = await client.fetch(`*[_type == "post" && defined(slug)] | order(pu ``` -[Check out this guide][guide] for a more elaborate introduction to how to integrate content from Sanity into Astro. +[Check out this guide][guide] for a more elaborate introduction to how to integrate content from Sanity into Astro. You can also look in the `examples` folder in this repository for complete implementation examples. ### Embedding Sanity Studio on a route @@ -114,14 +113,14 @@ You can use this configuration file to install plugins, add a schema with docume ```javascript // astro.config.mjs -import sanityIntegration from "@sanity/astro"; +import sanity from "@sanity/astro"; import { defineConfig } from "astro/config"; import react from "@astrojs/react"; export default defineConfig({ output: "hybrid", integrations: [ - sanityIntegration({ + sanity({ projectId: "3do82whm", dataset: "next", // Set useCdn to false if you're building statically. diff --git a/packages/sanity-astro/index.ts b/packages/sanity-astro/index.ts index e0a5fb3..c1607fa 100644 --- a/packages/sanity-astro/index.ts +++ b/packages/sanity-astro/index.ts @@ -1,18 +1,17 @@ import type { AstroIntegration } from "astro"; import type { SanityClient, ClientConfig } from "@sanity/client"; -import { vitePluginSanityInit } from "./vite-plugin-sanity-init"; +import type { Config } from "sanity"; +import { vitePluginSanityClient } from "./vite-plugin-sanity-client"; import { vitePluginSanityStudio } from "./vite-plugin-sanity-studio"; -declare global { - var sanityClientInstance: SanityClient; + +declare module "sanity:client" { + // eslint-disable-next-line + export const sanityClient: SanityClient; } -export function useSanityClient(): SanityClient { - if (!globalThis.sanityClientInstance) { - console.error( - "[@sanity/astro]: sanityClientInstance has not been initialized correctly", - ); - } - return globalThis.sanityClientInstance; +declare module "sanity:studio" { + // eslint-disable-next-line + export const studioConfig: Config; } export type IntegrationOptions = ClientConfig & { @@ -24,7 +23,7 @@ const defaultOptions: IntegrationOptions = { }; export default function sanityIntegration( - options: IntegrationOptions, + options: IntegrationOptions ): AstroIntegration { const resolvedOptions = { ...defaultOptions, @@ -38,11 +37,12 @@ export default function sanityIntegration( injectRoute, updateConfig, config, + logger, }) => { updateConfig({ vite: { plugins: [ - vitePluginSanityInit(resolvedOptions), + vitePluginSanityClient(resolvedOptions), vitePluginSanityStudio(resolvedOptions, config), ], }, @@ -58,9 +58,9 @@ export default function sanityIntegration( injectScript( "page-ssr", ` - import { sanityClientInstance } from "virtual:sanity-init"; - globalThis.sanityClientInstance = sanityClientInstance; - `, + import { sanityClient } from "sanity:client"; + globalThis.sanityClient = sanityClient; + ` ); }, }, diff --git a/packages/sanity-astro/studio/StudioComponent.tsx b/packages/sanity-astro/studio/StudioComponent.tsx index e249595..8729381 100644 --- a/packages/sanity-astro/studio/StudioComponent.tsx +++ b/packages/sanity-astro/studio/StudioComponent.tsx @@ -1,6 +1,6 @@ import React from "react"; // @ts-ignore -import config from "virtual:sanity-studio"; +import { config } from "sanity:studio"; import { Studio } from "sanity"; // import { useTheme } from "./useTheme"; @@ -8,7 +8,7 @@ import { Studio } from "sanity"; if (!config) { throw new Error( - "[@sanity/astro]: Can't load Sanity Studio. Check that you've configured it in `sanity.config.js|ts`.", + "[@sanity/astro]: Can't load Sanity Studio. Check that you've configured it in `sanity.config.js|ts`." ); } diff --git a/packages/sanity-astro/studio/usePrefersColorScheme.ts b/packages/sanity-astro/studio/usePrefersColorScheme.ts index 5cac971..91d0109 100644 --- a/packages/sanity-astro/studio/usePrefersColorScheme.ts +++ b/packages/sanity-astro/studio/usePrefersColorScheme.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ import type { ThemeColorSchemeKey } from "@sanity/ui"; import { useSyncExternalStore } from "react"; @@ -29,6 +28,6 @@ export function usePrefersColorScheme(): ThemeColorSchemeKey { return useSyncExternalStore( store.subscribe, store.getSnapshot, - store.getServerSnapshot, + store.getServerSnapshot ); } diff --git a/packages/sanity-astro/studio/useTheme.ts b/packages/sanity-astro/studio/useTheme.ts index 5affa22..e7becd8 100644 --- a/packages/sanity-astro/studio/useTheme.ts +++ b/packages/sanity-astro/studio/useTheme.ts @@ -4,13 +4,13 @@ import type { Config, SingleWorkspace, StudioTheme } from "sanity"; /** @alpha */ export function useTheme( - config?: Config | Required>, + config?: Config | Required> ): StudioTheme { const workspace = useMemo< SingleWorkspace | Required> | undefined >(() => (Array.isArray(config) ? config[0] : config), [config]); return useMemo( () => workspace?.theme || studioTheme, - [workspace], + [workspace] ); } diff --git a/packages/sanity-astro/vite-plugin-sanity-init.ts b/packages/sanity-astro/vite-plugin-sanity-client.ts similarity index 61% rename from packages/sanity-astro/vite-plugin-sanity-init.ts rename to packages/sanity-astro/vite-plugin-sanity-client.ts index ce32922..c9f69ea 100644 --- a/packages/sanity-astro/vite-plugin-sanity-init.ts +++ b/packages/sanity-astro/vite-plugin-sanity-client.ts @@ -1,12 +1,12 @@ import type { ClientConfig } from "@sanity/client"; import type { Plugin } from "vite"; -export function vitePluginSanityInit(config: ClientConfig): Plugin { - const virtualModuleId = "virtual:sanity-init"; - const resolvedVirtualModuleId = "\0" + virtualModuleId; +const virtualModuleId = "sanity:client"; +const resolvedVirtualModuleId = "\0" + virtualModuleId; +export function vitePluginSanityClient(config: ClientConfig): Plugin { return { - name: "vite-plugin-sanity-init", + name: "vite-plugin-sanity-client", resolveId(id: string) { if (id === virtualModuleId) { return resolvedVirtualModuleId; @@ -16,7 +16,7 @@ export function vitePluginSanityInit(config: ClientConfig): Plugin { if (id === resolvedVirtualModuleId) { return ` import { createClient } from "@sanity/client"; - export const sanityClientInstance = createClient( + export const sanityClient = createClient( ${JSON.stringify(config)} ); `; diff --git a/packages/sanity-astro/vite-plugin-sanity-studio.ts b/packages/sanity-astro/vite-plugin-sanity-studio.ts index bdccd29..5acec33 100644 --- a/packages/sanity-astro/vite-plugin-sanity-studio.ts +++ b/packages/sanity-astro/vite-plugin-sanity-studio.ts @@ -1,7 +1,7 @@ import type { Plugin } from "vite"; -export function vitePluginSanityStudio(resolvedOptions, config): Plugin { - const virtualModuleId = "virtual:sanity-studio"; +export function vitePluginSanityStudio(resolvedOptions, { output }): Plugin { + const virtualModuleId = "sanity:studio"; const resolvedVirtualModuleId = virtualModuleId; return { @@ -13,38 +13,40 @@ export function vitePluginSanityStudio(resolvedOptions, config): Plugin { return null; }, async load(id: string) { - if (id === "virtual:sanity-studio") { - if (config.output !== "hybrid" && config.output !== "server") { + if (id === virtualModuleId) { + if (output !== "hybrid" && output !== "server") { throw new Error( - "[@sanity/astro]: Sanity Studio requires `output: 'hybrid'` or `output: 'server'` in your Astro config", + "[@sanity/astro]: Sanity Studio requires `output: 'hybrid'` or `output: 'server'` in your Astro config" ); } const studioConfig = await this.resolve("/sanity.config"); if (!studioConfig) { throw new Error( - "[@sanity/astro]: Sanity Studio requires a `sanity.config.ts|js` file in your project root.", + "[@sanity/astro]: Sanity Studio requires a `sanity.config.ts|js` file in your project root." ); return null; } if (!resolvedOptions.studioBasePath) { throw new Error( - "[@sanity/astro]: The `studioBasePath` option is required in `astro.config.mjs`. For example — `studioBasePath: '/admin'`", + "[@sanity/astro]: The `studioBasePath` option is required in `astro.config.mjs`. For example — `studioBasePath: '/admin'`" ); } return ` - import config from "${studioConfig.id}"; - if (config.basePath) { - if (config.basePath !== "/${resolvedOptions.studioBasePath}") { + import studioConfig from "${studioConfig.id}"; + + if (studioConfig.basePath) { + if (studioConfig.basePath !== "/${resolvedOptions.studioBasePath}") { console.warn( "[@sanity/astro]: This integration ignores the basePath setting in sanity.config.ts|js. To set the basePath for Sanity Studio, use the studioBasePath option in astro.config.mjs and remove it from sanity.config.ts."); } } - export default { - ...config, + export const config = { + ...studioConfig, // override basePath from sanity.config.ts|js with plugin setting - basePath: "/${resolvedOptions.studioBasePath}", - }`; + basePath: "${resolvedOptions.studioBasePath}", + } + `; } return null; },