Added preview functionality for home page

This commit is contained in:
Henrik Larsson 2023-08-14 23:22:54 +02:00
parent 31b5f2a8b9
commit bfdfeeaf97
25 changed files with 263 additions and 327 deletions

View File

@ -1,10 +1,10 @@
import CategoryPage from '@/components/pages/category-page';
import ProductPage from '@/components/pages/product-page';
import SinglePage from '@/components/pages/single-page';
import getQueryFromSlug from '@/helpers/get-query-from-slug'; import getQueryFromSlug from '@/helpers/get-query-from-slug';
import { clientFetch } from 'lib/sanity/sanity.client'; import { getCachedClient } from 'lib/sanity/sanity.client';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
import CategoryPage from './pages/category-page';
import ProductPage from './pages/product-page';
import SinglePage from './pages/single-page';
export const revalidate = 43200; // 12 hours in seconds export const revalidate = 43200; // 12 hours in seconds
@ -17,7 +17,7 @@ export async function generateMetadata({
const { query = '', queryParams } = getQueryFromSlug(slug, locale); const { query = '', queryParams } = getQueryFromSlug(slug, locale);
const page = await clientFetch(query, queryParams); const page = await getCachedClient()(query, queryParams);
if (!page) return notFound(); if (!page) return notFound();
@ -47,11 +47,11 @@ export default async function Page({ params }: PageParams) {
let pageData; let pageData;
if (docType === 'page') { if (docType === 'page') {
pageData = await clientFetch(query, queryParams); pageData = await getCachedClient()(query, queryParams);
} else if (docType === 'product') { } else if (docType === 'product') {
pageData = await clientFetch(query, queryParams); pageData = await getCachedClient()(query, queryParams);
} else if (docType === 'category') { } else if (docType === 'category') {
pageData = await clientFetch(query, queryParams); pageData = await getCachedClient()(query, queryParams);
} else { } else {
return; return;
} }

View File

@ -1,17 +1,18 @@
import DynamicContentManager from 'components/layout/dynamic-content-manager/dynamic-content-manager'; import HomePage from '@/components/pages/home-page';
import HomePagePreview from '@/components/pages/home-page-preview';
import PreviewProvider from '@/components/preview-provider';
import { homePageQuery } from 'lib/sanity/queries'; import { homePageQuery } from 'lib/sanity/queries';
import { clientFetch } from 'lib/sanity/sanity.client'; import { getCachedClient } from 'lib/sanity/sanity.client';
import { Metadata } from 'next'; import { Metadata } from 'next';
import { draftMode } from 'next/headers';
import { notFound } from 'next/navigation'; import { notFound } from 'next/navigation';
export const runtime = 'edge';
export async function generateMetadata({ export async function generateMetadata({
params params
}: { }: {
params: { slug: string; locale: string }; params: { slug: string; locale: string };
}): Promise<Metadata> { }): Promise<Metadata> {
const homePage = await clientFetch(homePageQuery, params); const homePage = await getCachedClient()(homePageQuery, params);
if (!homePage) return notFound(); if (!homePage) return notFound();
@ -20,19 +21,26 @@ export async function generateMetadata({
description: homePage.seo.description || homePage.description description: homePage.seo.description || homePage.description
}; };
} }
interface HomePageParams { interface HomePageParams {
params: { params: {
locale: string; locale: string;
}; };
} }
export default async function HomePage({ params }: HomePageParams) { export default async function IndexPage({ params }: HomePageParams) {
const data = await clientFetch(homePageQuery, params); const preview = draftMode().isEnabled ? { token: process.env.SANITY_API_READ_TOKEN } : undefined;
const data = await getCachedClient(preview)(homePageQuery, params);
if (!data) return notFound();
if (preview && preview.token) {
return ( return (
<> <PreviewProvider token={preview.token}>
<DynamicContentManager content={data?.content} /> <HomePagePreview initialData={data} params={params} />
</> </PreviewProvider>
); );
}
return <HomePage data={data} />;
} }

View File

@ -1,99 +0,0 @@
// route handler enabling draft mode
import { categoryQuery, homePageQuery, pageQuery, productQuery } from 'lib/sanity/queries';
import { client } from 'lib/sanity/sanity.client';
import { draftMode } from 'next/headers';
const draftSecret = process.env.NEXT_PUBLIC_SANITY_DRAFT_TOKEN
export async function GET(request: Request) {
// Enable Draft Mode by setting the cookie
draftMode().enable();
// Parse query string parameters
const { searchParams } = new URL(request.url);
const secret = searchParams.get('secret');
const slug = searchParams.get('slug');
const locale = searchParams.get('locale');
const type = searchParams.get('type');
// Make sure there's a valid draft token.
if (secret !== draftSecret) {
return new Response('Invalid token', { status: 401 });
}
// Make sure there's a slug provided.
if (!slug) {
return new Response('No slug provided', { status: 401 });
}
// Make sure there's a locale provided.
if (!locale) {
return new Response('No locale provided', { status: 401 });
}
// Make sure there's a type provided.
if (!type) {
return new Response('No type provided', { status: 401 });
}
// Types available for preview - Check if the post with the given `slug` exists
const home = await client.fetch(homePageQuery, {
slug: slug,
locale: locale,
})
const page = await client.fetch(pageQuery, {
slug: slug,
locale: locale,
})
const product = await client.fetch(productQuery, {
slug: slug,
locale: locale,
})
const category = await client.fetch(categoryQuery, {
slug: slug,
locale: locale,
})
draftMode().enable();
// Redirect to the path from the fetched post
// We don't redirect to req.query.slug as that might lead to open redirect vulnerabilities
if (home && type === 'home') {
return new Response(null, {
status: 307,
headers: {
Location: `/${home.locale}/${home.slug}`,
},
})
}
if (page && type === 'page') {
return new Response(null, {
status: 307,
headers: {
Location: `/${page.locale}/${page.slug}`,
},
})
}
if (product && type === 'product') {
return new Response(null, {
status: 307,
headers: {
Location: `/${product.locale}/product/${product.slug}`,
},
})
}
if (category && type === 'category') {
return new Response(null, {
status: 307,
headers: {
Location: `/${category.locale}/category/${category.slug}`,
},
})
}
}

View File

@ -1,12 +0,0 @@
import { draftMode } from 'next/headers';
export async function GET() {
draftMode().disable();
return new Response(null, {
status: 307,
headers: {
Location: `/`,
},
})
}

View File

@ -0,0 +1,12 @@
import { draftMode } from "next/headers";
export async function GET() {
draftMode().disable();
return new Response(null, {
status: 307,
headers: {
Location: `/`,
},
})
}

27
app/api/preview/route.ts Normal file
View File

@ -0,0 +1,27 @@
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
// const slug = searchParams.get('slug')
const type = searchParams.get('type')
const locale = searchParams.get('locale')
// Check the secret and next parameters
// This secret should only be known to this route handler and the CMS
if (secret !== process.env.SANITY_API_READ_TOKEN) {
return new Response('Invalid token', { status: 401 })
}
draftMode().enable()
if (type === 'home') {
return new Response(null, {
status: 307,
headers: {
Location: `/${locale}`,
},
})
}
}

View File

@ -9,81 +9,6 @@ import USPSection from '@/components/modules/usp-section/usp-section';
import { InformationCircleIcon } from '@heroicons/react/24/outline'; import { InformationCircleIcon } from '@heroicons/react/24/outline';
import { Suspense } from 'react'; import { Suspense } from 'react';
// interface getContentComponentProps {
// _type: string;
// _key: number;
// disabled: boolean;
// }
// const getContentComponent = ({ _type, _key, disabled, ...rest }: getContentComponentProps) => {
// let Component: any;
// switch (_type) {
// case 'hero':
// if (disabled !== true) {
// Component = Hero;
// } else {
// return;
// }
// break;
// case 'slider':
// if (disabled !== true) {
// Component = Slider;
// } else {
// return;
// }
// break;
// case 'filteredProductList':
// if (disabled !== true) {
// Component = FilteredProductList;
// } else {
// return;
// }
// break;
// case 'blurbSection':
// if (disabled !== true) {
// Component = BlurbSection;
// } else {
// return;
// }
// break;
// case 'uspSection':
// if (disabled !== true) {
// Component = USPSection;
// } else {
// return;
// }
// break;
// case 'reusableSection':
// if (disabled !== true) {
// Component = ReusableSection;
// } else {
// return;
// }
// break;
// default:
// return (
// <div
// className={`px-4 lg:px-8 2xl:px-16 ${
// process.env.NODE_ENV === 'production' ? 'hidden' : ''
// }`}
// key={`index-${_key}`}
// >
// <span className="inline-flex items-center bg-red p-2 text-sm font-bold">
// <InformationCircleIcon className="mr-1" />
// {`No matching component (Type: ${_type})`}
// </span>
// </div>
// );
// }
// return Component ? (
// <Component key={`${_key}`} {...rest} />
// ) : (
// <div key={`${_key}`}>Something else</div>
// );
// };
interface dynamicContentManagerProps { interface dynamicContentManagerProps {
content: [] | any; content: [] | any;
} }
@ -91,7 +16,7 @@ interface dynamicContentManagerProps {
const DynamicContentManager = ({ content }: dynamicContentManagerProps) => { const DynamicContentManager = ({ content }: dynamicContentManagerProps) => {
return ( return (
<div className="dynamic-content overflow-x-hidden"> <div className="dynamic-content overflow-x-hidden">
{content.map( {content?.map(
( (
component: { _type: string; _key: number; disabled: boolean; rest: any } | any, component: { _type: string; _key: number; disabled: boolean; rest: any } | any,
index: number index: number

View File

@ -1,6 +1,6 @@
import Text from '@/components/ui/text'; import Text from '@/components/ui/text';
import { footerMenusQuery } from '@/lib/sanity/queries'; import { footerMenusQuery } from '@/lib/sanity/queries';
import { clientFetch } from '@/lib/sanity/sanity.client'; import { getCachedClient } from '@/lib/sanity/sanity.client';
import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher'; import LocaleSwitcher from 'components/ui/locale-switcher/locale-switcher';
import Logo from 'components/ui/logo/logo'; import Logo from 'components/ui/logo/logo';
import Link from 'next/link'; import Link from 'next/link';
@ -15,7 +15,7 @@ export default async function Footer({ locale }: FooterProps) {
locale: locale locale: locale
}; };
const footerMenus = await clientFetch(footerMenusQuery, params); const footerMenus = await getCachedClient()(footerMenusQuery, params);
return ( return (
<footer className="border-t border-ui-border bg-app"> <footer className="border-t border-ui-border bg-app">

View File

@ -1,5 +1,5 @@
import { categoriesQuery } from '@/lib/sanity/queries'; import { categoriesQuery } from '@/lib/sanity/queries';
import { clientFetch } from '@/lib/sanity/sanity.client'; import { getCachedClient } from '@/lib/sanity/sanity.client';
import Cart from 'components/cart'; import Cart from 'components/cart';
import OpenCart from 'components/cart/open-cart'; import OpenCart from 'components/cart/open-cart';
import Logo from 'components/ui/logo/logo'; import Logo from 'components/ui/logo/logo';
@ -21,7 +21,7 @@ export default async function Header({ locale }: HeaderProps) {
const params = { const params = {
locale: locale locale: locale
}; };
const mainMenu = await clientFetch(categoriesQuery, params); const mainMenu = await getCachedClient()(categoriesQuery, params);
return ( return (
<HeaderRoot> <HeaderRoot>

View File

@ -0,0 +1,24 @@
'use client';
import { homePageQuery } from '@/lib/sanity/queries';
import { useLiveQuery } from '@sanity/preview-kit';
import PreviewBanner from '../ui/preview-banner';
import HomePage from './home-page';
interface HomePagePreviewParams {
initialData: [];
params: {
locale: string;
};
}
export default function HomePagePreview({ initialData, params }: HomePagePreviewParams) {
const [data] = useLiveQuery(initialData, homePageQuery, params);
return (
<>
<HomePage data={data} />;{/* @ts-ignore */}
<PreviewBanner title={data?.title} />
</>
);
}

View File

@ -0,0 +1,13 @@
import DynamicContentManager from '@/components/layout/dynamic-content-manager/dynamic-content-manager';
interface IndexPageParams {
data: object | any;
}
export default function HomePage({ data }: IndexPageParams) {
return (
<>
<DynamicContentManager content={data?.content} />;
</>
);
}

View File

@ -0,0 +1,16 @@
'use client';
import { getClient } from '@/lib/sanity/sanity.client';
import { LiveQueryProvider } from '@sanity/preview-kit';
import { useMemo } from 'react';
export default function PreviewProvider({
children,
token
}: {
children: React.ReactNode;
token: string;
}) {
const client = useMemo(() => getClient({ token }), [token]);
return <LiveQueryProvider client={client}>{children}</LiveQueryProvider>;
}

View File

@ -1,29 +1,30 @@
'use client' 'use client';
import { useTranslations } from 'next-intl' import { useTranslations } from 'next-intl';
import Link from 'next/link' import Link from 'next/link';
interface PreviewBannerProps { interface PreviewBannerProps {
title?: string title?: string;
} }
const PreviewBanner = ({ title }: PreviewBannerProps) => { const PreviewBanner = ({ title }: PreviewBannerProps) => {
const t = useTranslations('ui.previewBanner') const t = useTranslations('ui.previewBanner');
return ( return (
<div className="flex justify-between items-center bg-app border-t border-high-contrast w-full fixed bottom-0 right-0 p-6 z-50"> <div className="fixed bottom-0 right-0 z-50 flex w-full items-center justify-between border-t border-high-contrast bg-app p-6">
{title && ( {title && (
<p className="text-lg"> <p className="text-lg">
{t('titlePart')} <span className="italic font-bold">{title}</span> {t('titlePart')} <span className="font-bold italic">{title}</span>
</p> </p>
)} )}
<Link <Link
className="bg-blue transition-colors duration-100 text-center px-6 py-4 text-white font-bold hover:bg-opacity-80 focus:bg-opacity-80" className="bg-blue px-6 py-4 text-center font-bold text-white transition-colors duration-100 hover:bg-opacity-80 focus:bg-opacity-80"
href="/api/exit-draft" href="/api/exit-preview"
prefetch={false}
> >
{t('exitPreviewLabel')} {t('exitPreviewLabel')}
</Link> </Link>
</div> </div>
) );
} };
export default PreviewBanner export default PreviewBanner;

View File

@ -41,8 +41,10 @@ export const SANITY_API_VERSION = '2022-10-25'
// Set this to enable helper links in document status banners and shortcut links on products and collections. // Set this to enable helper links in document status banners and shortcut links on products and collections.
export const STORM_STORE_ID = '' export const STORM_STORE_ID = ''
export const SANITY_STUDIO_API_READ_TOKEN = process.env.SANITY_STUDIO_API_READ_TOKEN;
// Project preview URLs // Project preview URLs
export const localStorefrontUrl = 'http://localhost:3000'; export const localStorefrontUrl = 'http://localhost:3000';
export const localStorefrontPreviewUrl = 'http://localhost:3000/api/draft'; export const localStorefrontPreviewUrl = 'http://localhost:3000/api/preview';
export const publicStorefrontUrl = 'https://km-storefront.vercel.app'; export const publicStorefrontUrl = 'https://km-storefront.vercel.app';
export const publicStorefrontPreviewUrl = 'https://km-storefront.vercel.app/api/draft'; export const publicStorefrontPreviewUrl = 'https://km-storefront.vercel.app/api/preview';

View File

@ -1,8 +1,8 @@
import {ListItemBuilder} from 'sanity/desk' import { EyeOpenIcon, MasterDetailIcon } from '@sanity/icons'
import defineStructure from '../utils/define-structure' import { SanityDocument } from 'sanity'
import Iframe from 'sanity-plugin-iframe-pane' import Iframe from 'sanity-plugin-iframe-pane'
import {SanityDocument} from 'sanity' import { ListItemBuilder } from 'sanity/desk'
import {EyeOpenIcon, MasterDetailIcon} from '@sanity/icons' import defineStructure from '../utils/define-structure'
import getPreviewUrl from '../utils/get-preview-url' import getPreviewUrl from '../utils/get-preview-url'
export default defineStructure<ListItemBuilder>((S) => export default defineStructure<ListItemBuilder>((S) =>

View File

@ -1,15 +1,31 @@
import { createClient } from "next-sanity"; import type { SanityClient } from "@sanity/client";
import { cache } from 'react'; import { createClient } from "@sanity/client";
import { cache } from "react";
export const projectId = process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!; export function getClient(preview?: {token?: string}): SanityClient {
export const dataset = process.env.NEXT_PUBLIC_SANITY_DATASET!; const client = createClient({
const apiVersion = process.env.NEXT_PUBLIC_SANITY_API_VERSION!; projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
export const client = createClient({ apiVersion: process.env.NEXT_PUBLIC_SANITY_API_VERSION,
projectId,
dataset,
apiVersion,
useCdn: true, useCdn: true,
}); perspective: 'published',
})
if (preview) {
if (!preview.token) {
throw new Error('You must provide a token to preview drafts')
}
return client.withConfig({
token: preview.token,
useCdn: false,
ignoreBrowserTokenWarning: true,
perspective: 'previewDrafts',
})
}
return client
}
export const clientFetch = cache(client.fetch.bind(client)); export const getCachedClient = (preview?: {token?: string}) => {
const client = getClient(preview);
return cache(client.fetch.bind(client));
};

View File

@ -1,7 +1,7 @@
import createImageUrlBuilder from '@sanity/image-url' import createImageUrlBuilder from '@sanity/image-url'
import { client } from './sanity.client' import { getClient } from './sanity.client'
export const imageBuilder = createImageUrlBuilder(client) export const imageBuilder = createImageUrlBuilder(getClient())
export const urlForImage = (source: any) => export const urlForImage = (source: any) =>
imageBuilder.image(source).auto('format').fit('crop') imageBuilder.image(source).auto('format').fit('crop')

View File

@ -1,20 +1,24 @@
// @ts-nocheck // @ts-nocheck
import {isDev, SanityDocument} from 'sanity' import { isDev, SanityDocument } from 'sanity'
import { localStorefrontPreviewUrl, publicStorefrontPreviewUrl } from '../constants' import { localStorefrontPreviewUrl, publicStorefrontPreviewUrl } from '../constants'
const SANITY_STUDIO_API_READ_TOKEN = "skYG2HXNga8uxSL7rFIreJEnP0SdVjCZ2nzB8rUHD4wRWxXPGceXTuR5vCVBP99mWZ9ULhghmpUyX7EtzDmJusSk6Gwvdr3nLAsdWI9ZktIWvSWUNpHbu0Xfrrt0UUaktrLglk7ToABvjXlaPHLpOIR3dnjl4MGByutPmyra0b5t20kgDrmF"
// Customise this function to show the correct URL based on the current document // Customise this function to show the correct URL based on the current document
export default function getPreviewUrl(doc: SanityDocument) { export default async function getPreviewUrl(doc: SanityDocument) {
if (isDev) { if (isDev) {
// Home page have no slugs.
if (!doc.slug) { if (!doc.slug) {
return return `${localStorefrontPreviewUrl}?locale=${doc.language}&type=${doc._type}&secret=${SANITY_STUDIO_API_READ_TOKEN}`
} }
return `${localStorefrontPreviewUrl}?slug=${doc.slug.current}&locale=${doc.language}&secret=secret&type=${doc._type}` return `${localStorefrontPreviewUrl}?slug=${doc.slug.current}&locale=${doc.language}&type=${doc._type}&secret=${SANITY_STUDIO_API_READ_TOKEN}`
} else { } else {
// Home page have no slugs.
if (!doc.slug) { if (!doc.slug) {
return return `${localStorefrontPreviewUrl}?locale=${doc.language}&type=${doc._type}&secret=${SANITY_STUDIO_API_READ_TOKEN}`
} }
return `${publicStorefrontPreviewUrl}?slug=${doc.slug.current}&locale=${doc.language}&secret=secret&type=${doc._type}` return `${publicStorefrontPreviewUrl}?slug=${doc.slug.current}&locale=${doc.language}&type=${doc._type}&secret=${SANITY_STUDIO_API_READ_TOKEN}`
} }
} }

View File

@ -24,7 +24,12 @@ module.exports = withBundleAnalyzer(
}, },
images: { images: {
formats: ['image/avif', 'image/webp'], formats: ['image/avif', 'image/webp'],
domains: ['cdn.sanity.io'], remotePatterns: [
{
protocol: 'https',
hostname: 'cdn.sanity.io',
},
],
}, },
} }
); );

View File

@ -20,7 +20,7 @@
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.0.18", "@heroicons/react": "^2.0.18",
"@portabletext/react": "^3.0.0", "@portabletext/react": "^3.0.4",
"@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.4", "@radix-ui/react-dropdown-menu": "^2.0.4",
@ -43,7 +43,7 @@
"is-empty-iterable": "^3.0.0", "is-empty-iterable": "^3.0.0",
"next": "13.4.13", "next": "13.4.13",
"next-intl": "2.19.1", "next-intl": "2.19.1",
"next-sanity": "^4.3.2", "next-sanity": "^5.3.0",
"react": "18.2.0", "react": "18.2.0",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
"react-dom": "18.2.0", "react-dom": "18.2.0",

126
pnpm-lock.yaml generated
View File

@ -9,7 +9,7 @@ dependencies:
specifier: ^2.0.18 specifier: ^2.0.18
version: 2.0.18(react@18.2.0) version: 2.0.18(react@18.2.0)
'@portabletext/react': '@portabletext/react':
specifier: ^3.0.0 specifier: ^3.0.4
version: 3.0.4(react@18.2.0) version: 3.0.4(react@18.2.0)
'@radix-ui/react-accordion': '@radix-ui/react-accordion':
specifier: ^1.1.2 specifier: ^1.1.2
@ -78,8 +78,8 @@ dependencies:
specifier: 2.19.1 specifier: 2.19.1
version: 2.19.1(next@13.4.13)(react@18.2.0) version: 2.19.1(next@13.4.13)(react@18.2.0)
next-sanity: next-sanity:
specifier: ^4.3.2 specifier: ^5.3.0
version: 4.3.3(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.13)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11) version: 5.3.0(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.13)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11)
react: react:
specifier: 18.2.0 specifier: 18.2.0
version: 18.2.0 version: 18.2.0
@ -2218,23 +2218,6 @@ packages:
resolution: {integrity: sha512-wtMYcV5GIDIhVyF/jjmdwq1GdlK07dRL40XMns73VbrFI7FteRltxv48bhYVZPcLkRXb0SHjpDS/icj9/yzbVA==} resolution: {integrity: sha512-wtMYcV5GIDIhVyF/jjmdwq1GdlK07dRL40XMns73VbrFI7FteRltxv48bhYVZPcLkRXb0SHjpDS/icj9/yzbVA==}
dev: false dev: false
/@sanity/groq-store@2.3.4:
resolution: {integrity: sha512-7W3ROK858YuAjyoPp9+OfHj00BkJX172b6LyV9peL8DcbMIG0G621Tv+oULLaizkA4y2D+b1sx+AYHWtdtIrew==}
engines: {node: '>=14.18'}
dependencies:
'@sanity/eventsource': 5.0.0
'@sanity/types': 3.15.0
fast-deep-equal: 3.1.3
groq: 3.15.0
groq-js: 1.1.10
mendoza: 2.1.2
simple-get: 4.0.1
split2: 4.2.0
throttle-debounce: 5.0.0
transitivePeerDependencies:
- supports-color
dev: false
/@sanity/groq-store@4.0.3: /@sanity/groq-store@4.0.3:
resolution: {integrity: sha512-6mXBUvOrsSG9G7OP52VQMd114+s1AjkrJZCUIaFlZGJTamFvd8viCgZuykEt5wURIm3nVnx3MmWDZPFCvLvNuQ==} resolution: {integrity: sha512-6mXBUvOrsSG9G7OP52VQMd114+s1AjkrJZCUIaFlZGJTamFvd8viCgZuykEt5wURIm3nVnx3MmWDZPFCvLvNuQ==}
engines: {node: '>=14.18'} engines: {node: '>=14.18'}
@ -2252,6 +2235,23 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@sanity/groq-store@4.0.4:
resolution: {integrity: sha512-Bk1ZsS6PGeCtmP8a4FJfvHws1WlnQUPdcr9MbO38Fbbtp55ZdLjTbxozxo//mK7jsbmNxf2HjpQ1mm5jDI49RQ==}
engines: {node: '>=14.18'}
dependencies:
'@sanity/eventsource': 5.0.0
'@sanity/types': 3.15.0
fast-deep-equal: 3.1.3
groq: 3.15.0
groq-js: 1.1.12
mendoza: 3.0.3
simple-get: 4.0.1
split2: 4.2.0
throttle-debounce: 5.0.0
transitivePeerDependencies:
- supports-color
dev: false
/@sanity/icons@1.3.10(react@18.2.0): /@sanity/icons@1.3.10(react@18.2.0):
resolution: {integrity: sha512-5wVG/vIiGuGrSmq+Bl3PY7XDgQrGv0fyHdJI64FSulnr2wH3NMqZ6C59UFxnrZ93sr7kOt0zQFoNv2lkPBi0Cg==} resolution: {integrity: sha512-5wVG/vIiGuGrSmq+Bl3PY7XDgQrGv0fyHdJI64FSulnr2wH3NMqZ6C59UFxnrZ93sr7kOt0zQFoNv2lkPBi0Cg==}
peerDependencies: peerDependencies:
@ -2381,24 +2381,6 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@sanity/preview-kit@1.5.5(react@18.2.0):
resolution: {integrity: sha512-RJ+bcLB0cH2vyzqyhb4WMua3xygx4em2fuooKOETo1Z/HyyXqFfWZgCRvFItLS5erKNr0pz7Mbhq7sWhGmuOtg==}
engines: {node: '>=14'}
peerDependencies:
react: ^18.0.0
dependencies:
'@sanity/client': 6.4.4
'@sanity/eventsource': 5.0.0
'@sanity/groq-store': 2.3.4
'@vercel/stega': 0.0.5
lodash.isplainobject: 4.0.6
react: 18.2.0
suspend-react: 0.0.10(react@18.2.0)
tiny-invariant: 1.3.1
transitivePeerDependencies:
- supports-color
dev: false
/@sanity/preview-kit@2.4.9(@sanity/client@6.4.4)(react@18.2.0): /@sanity/preview-kit@2.4.9(@sanity/client@6.4.4)(react@18.2.0):
resolution: {integrity: sha512-0j7An0beiMOTMLA+RdzQmAo6Lk6YuKuuARabKTk6rpl4uf117jtveh50DiaZNHieToF9AGXxc9qgYXR0lc4k+w==} resolution: {integrity: sha512-0j7An0beiMOTMLA+RdzQmAo6Lk6YuKuuARabKTk6rpl4uf117jtveh50DiaZNHieToF9AGXxc9qgYXR0lc4k+w==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -2424,6 +2406,31 @@ packages:
- supports-color - supports-color
dev: false dev: false
/@sanity/preview-kit@3.0.0(@sanity/client@6.4.4)(react@18.2.0):
resolution: {integrity: sha512-LF83FQJ0kZgB8Dz8nolseiXh+AsX0UaNd3GhNLMrsmSjy6GCagNyQzCpadysQyuBZHftXgMN/fQ0/gfoMjNSDA==}
engines: {node: '>=14'}
peerDependencies:
'@sanity/client': ^6.4.6
react: ^18.0.0
peerDependenciesMeta:
react:
optional: true
dependencies:
'@sanity/client': 6.4.4
'@sanity/eventsource': 5.0.0
'@sanity/groq-store': 4.0.4
'@vercel/stega': 0.1.0
lodash.get: 4.4.2
lodash.isplainobject: 4.0.6
lru-cache: 10.0.1
mendoza: 3.0.3
react: 18.2.0
react-fast-compare: 3.2.2
use-sync-external-store: 1.2.0(react@18.2.0)
transitivePeerDependencies:
- supports-color
dev: false
/@sanity/schema@3.15.0: /@sanity/schema@3.15.0:
resolution: {integrity: sha512-x6KSZkfBnVPFkHyuCKcaXZbu8C76qUkRtczZ5DNvFQbIxHYGMzUuQTDm7JBATt1c3KKM4nSR5xXwsh6IzuM5+w==} resolution: {integrity: sha512-x6KSZkfBnVPFkHyuCKcaXZbu8C76qUkRtczZ5DNvFQbIxHYGMzUuQTDm7JBATt1c3KKM4nSR5xXwsh6IzuM5+w==}
dependencies: dependencies:
@ -2927,10 +2934,6 @@ packages:
ajv: 6.12.6 ajv: 6.12.6
dev: false dev: false
/@vercel/stega@0.0.5:
resolution: {integrity: sha512-vvuUYW0rBp4Ea9xv0LilqFyDHAW9tvy4GL70G1ayGisQwpOYIPChmiw/56jqZvpxjE9gjQIApLfglOcdZe3PcA==}
dev: false
/@vercel/stega@0.1.0: /@vercel/stega@0.1.0:
resolution: {integrity: sha512-5b0PkOJsFBX5alChuIO3qpkt5vIZBevzLPhUQ1UP8UzVjL3F1VllnZxp/thfD8R5ol7D7WHkgZHIjdUBX4tDpQ==} resolution: {integrity: sha512-5b0PkOJsFBX5alChuIO3qpkt5vIZBevzLPhUQ1UP8UzVjL3F1VllnZxp/thfD8R5ol7D7WHkgZHIjdUBX4tDpQ==}
dev: false dev: false
@ -5065,13 +5068,13 @@ packages:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
dev: true dev: true
/groq-js@1.1.10: /groq-js@1.1.11:
resolution: {integrity: sha512-cYZMSCuBZ5KPB7hDRzkIwTB6qTDtcfqXxcejJPWumSw5gCOInTSvVtfccp0GM7TE1HkF7bF1PR2iSnliFDSSJg==} resolution: {integrity: sha512-LLYg7+nuOOcbQD7FKJjZj442W4ws+j/yggJV474VS6kmeIpBxfNGNMnBsfGSaJ/iDIhknjL4OcDgJ60FL+UJXA==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
dev: false dev: false
/groq-js@1.1.11: /groq-js@1.1.12:
resolution: {integrity: sha512-LLYg7+nuOOcbQD7FKJjZj442W4ws+j/yggJV474VS6kmeIpBxfNGNMnBsfGSaJ/iDIhknjL4OcDgJ60FL+UJXA==} resolution: {integrity: sha512-02KhsoLuTwr/MOf6bBzt+rQOj+QuLoZ5IDDkzXM2NWY73CF1d29KTRBffzCAjsjBvY7kn+oQcwPdQVb3vBkl9w==}
engines: {node: '>= 14'} engines: {node: '>= 14'}
dev: false dev: false
@ -5889,6 +5892,11 @@ packages:
engines: {node: 14 || >=16.14} engines: {node: 14 || >=16.14}
dev: false dev: false
/lru-cache@10.0.1:
resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==}
engines: {node: 14 || >=16.14}
dev: false
/lru-cache@5.1.1: /lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
dependencies: dependencies:
@ -5920,11 +5928,6 @@ packages:
resolution: {integrity: sha512-mXfNXte0RSWl0rEIsQhXutfM2R2Oa7UyKDD7XoZMEbKeucTRms04y5y41U8gLqPzRx7ViN/QyYnTR2TX/5tawA==} resolution: {integrity: sha512-mXfNXte0RSWl0rEIsQhXutfM2R2Oa7UyKDD7XoZMEbKeucTRms04y5y41U8gLqPzRx7ViN/QyYnTR2TX/5tawA==}
dev: false dev: false
/mendoza@2.1.2:
resolution: {integrity: sha512-Z2orUYO/RR7hJ2WdMtE1+u7X3/FiZrUpZqdctjxjxAfRODHfSvHKH+5tdEq/dXCf3W3CXSqWM46Ye7ww+KMrtQ==}
engines: {node: '>=10'}
dev: false
/mendoza@3.0.3: /mendoza@3.0.3:
resolution: {integrity: sha512-xh0Angj7/kuLzJHglH7dVetoSyUt1/2wjmuugB0iBftteS6+xKvwC+bhs+IvF9tITdEdZpIl0XT5QLaL18A5dA==} resolution: {integrity: sha512-xh0Angj7/kuLzJHglH7dVetoSyUt1/2wjmuugB0iBftteS6+xKvwC+bhs+IvF9tITdEdZpIl0XT5QLaL18A5dA==}
engines: {node: '>=14.18'} engines: {node: '>=14.18'}
@ -6091,10 +6094,11 @@ packages:
use-intl: 2.19.1(react@18.2.0) use-intl: 2.19.1(react@18.2.0)
dev: false dev: false
/next-sanity@4.3.3(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.13)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11): /next-sanity@5.3.0(@sanity/client@6.4.4)(@sanity/icons@2.4.1)(@sanity/types@3.15.0)(@sanity/ui@1.7.4)(@types/styled-components@5.1.26)(next@13.4.13)(react@18.2.0)(sanity@3.15.0)(styled-components@5.3.11):
resolution: {integrity: sha512-537xLC4hpTgV3SGj6w4aXvBvm/nHdyZGtZ5IcZpH33p70J7UjptF4+D4FvWKZGPjF3v3SFk75AHjxWVPORL9RA==} resolution: {integrity: sha512-cBeO3QgIjR9UPjDedNfLT4m6vmeFlDn9HAVT/6q8CbMMf+bcpxQ94jpLGGkaPRzoeCy/XWKK4IXNQYDSs4ApIA==}
engines: {node: '>=16'} engines: {node: '>=16.14'}
peerDependencies: peerDependencies:
'@sanity/client': ^6.4.6
'@sanity/icons': ^2.0.0 '@sanity/icons': ^2.0.0
'@sanity/types': ^3.0.0 '@sanity/types': ^3.0.0
'@sanity/ui': ^1.0.0 '@sanity/ui': ^1.0.0
@ -6106,7 +6110,7 @@ packages:
dependencies: dependencies:
'@sanity/client': 6.4.4 '@sanity/client': 6.4.4
'@sanity/icons': 2.4.1(react@18.2.0) '@sanity/icons': 2.4.1(react@18.2.0)
'@sanity/preview-kit': 1.5.5(react@18.2.0) '@sanity/preview-kit': 3.0.0(@sanity/client@6.4.4)(react@18.2.0)
'@sanity/types': 3.15.0 '@sanity/types': 3.15.0
'@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11) '@sanity/ui': 1.7.4(react-dom@18.2.0)(react-is@18.2.0)(react@18.2.0)(styled-components@5.3.11)
'@sanity/webhook': 2.0.0 '@sanity/webhook': 2.0.0
@ -8150,14 +8154,6 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
/suspend-react@0.0.10(react@18.2.0):
resolution: {integrity: sha512-7yyJ1aBr9Ap4XZQOBaYlOelNcRc42zv50C0pVNOHfhW/DwTbHGFVZKKJsVndyQvQTv/fAkIO9TAMvGiSCjT0Zw==}
peerDependencies:
react: '>=17.0'
dependencies:
react: 18.2.0
dev: false
/suspend-react@0.0.8(react@18.2.0): /suspend-react@0.0.8(react@18.2.0):
resolution: {integrity: sha512-ZC3r8Hu1y0dIThzsGw0RLZplnX9yXwfItcvaIzJc2VQVi8TGyGDlu92syMB5ulybfvGLHAI5Ghzlk23UBPF8xg==} resolution: {integrity: sha512-ZC3r8Hu1y0dIThzsGw0RLZplnX9yXwfItcvaIzJc2VQVi8TGyGDlu92syMB5ulybfvGLHAI5Ghzlk23UBPF8xg==}
peerDependencies: peerDependencies:
@ -8303,10 +8299,6 @@ packages:
resolution: {integrity: sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==} resolution: {integrity: sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==}
dev: false dev: false
/tiny-invariant@1.3.1:
resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==}
dev: false
/tiny-warning@1.0.3: /tiny-warning@1.0.3:
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
dev: false dev: false

View File

@ -1,11 +1,11 @@
import {defineConfig, isDev} from 'sanity'
import {deskTool} from 'sanity/desk'
import {visionTool} from '@sanity/vision'
import {media} from 'sanity-plugin-media'
import {schemaTypes} from '@/lib/sanity/schemas'
import {structure} from '@/lib/sanity/desk'
import Kodamera from '@/lib/sanity/components/icons/kodamera' import Kodamera from '@/lib/sanity/components/icons/kodamera'
import {documentInternationalization} from '@sanity/document-internationalization' import { structure } from '@/lib/sanity/desk'
import { schemaTypes } from '@/lib/sanity/schemas'
import { documentInternationalization } from '@sanity/document-internationalization'
import { visionTool } from '@sanity/vision'
import { defineConfig, isDev } from 'sanity'
import { media } from 'sanity-plugin-media'
import { deskTool } from 'sanity/desk'
const devOnlyPlugins = [visionTool()] const devOnlyPlugins = [visionTool()]
@ -15,6 +15,8 @@ const singletonActions = new Set(["publish", "discardChanges", "restore"])
// Define the singleton document types // Define the singleton document types
const singletonTypes = new Set(["settings", "home", "utilityMenu", "media.tag"]) const singletonTypes = new Set(["settings", "home", "utilityMenu", "media.tag"])
// console.log(process.env.SANITY_API_READ_TOKEN)
export default defineConfig({ export default defineConfig({
name: 'default', name: 'default',
title: 'KM Storefront CMS', title: 'KM Storefront CMS',