From b9220f497e693d20643f980be58e5a759498d745 Mon Sep 17 00:00:00 2001 From: Tobias Stikvoort Date: Fri, 12 Jul 2024 13:18:07 +0200 Subject: [PATCH] adds check for language --- src/client.ts | 4 ++-- src/hooks/usePageTree.ts | 4 ++-- src/hooks/usePageTreeItem.ts | 4 ++-- src/next.ts | 4 ++-- src/queries/index.ts | 19 ++++++++++++------- src/types.ts | 2 ++ src/validators/parent-validator.ts | 28 +++++++++++++++++----------- src/validators/slug-validator.ts | 4 ++-- 8 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/client.ts b/src/client.ts index 2358900..8355537 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,7 +1,7 @@ import { SanityClient } from 'sanity'; import { getAllPageMetadata } from './helpers/page-tree'; -import { getRawPageMetadataQuery } from './queries'; +import { getAllRawPageMetadataQuery } from './queries'; import { PageMetadata, PageTreeConfig } from './types'; export type { PageMetadata } from './types'; @@ -25,7 +25,7 @@ class PageTreeClient { } public async getAllPageMetadata(): Promise { - const rawPageMetadata = await this.client.fetch(getRawPageMetadataQuery(this.config)); + const rawPageMetadata = await this.client.fetch(getAllRawPageMetadataQuery(this.config)); return getAllPageMetadata(this.config, rawPageMetadata); } } diff --git a/src/hooks/usePageTree.ts b/src/hooks/usePageTree.ts index 0e156c1..3788409 100644 --- a/src/hooks/usePageTree.ts +++ b/src/hooks/usePageTree.ts @@ -2,11 +2,11 @@ import { useMemo } from 'react'; import { useListeningQuery } from 'sanity-plugin-utils'; import { mapRawPageMetadatasToPageTree } from '../helpers/page-tree'; -import { getRawPageMetadataQuery } from '../queries'; +import { getAllRawPageMetadataQuery } from '../queries'; import { PageTreeConfig, RawPageMetadata } from '../types'; export const usePageTree = (config: PageTreeConfig) => { - const { data, loading } = useListeningQuery(getRawPageMetadataQuery(config), { + const { data, loading } = useListeningQuery(getAllRawPageMetadataQuery(config), { options: { apiVersion: config.apiVersion }, }); diff --git a/src/hooks/usePageTreeItem.ts b/src/hooks/usePageTreeItem.ts index 4a4de90..43a89e0 100644 --- a/src/hooks/usePageTreeItem.ts +++ b/src/hooks/usePageTreeItem.ts @@ -3,11 +3,11 @@ import { useMemo } from 'react'; import { useListeningQuery } from 'sanity-plugin-utils'; import { getAllPageMetadata } from '../helpers/page-tree'; -import { getRawPageMetadataQuery } from '../queries'; +import { getAllRawPageMetadataQuery } from '../queries'; import { PageTreeConfig, RawPageMetadata } from '../types'; export const usePageTreeItem = (documentId: string, config: PageTreeConfig, perspective?: ClientPerspective) => { - const { data, loading } = useListeningQuery(getRawPageMetadataQuery(config), { + const { data, loading } = useListeningQuery(getAllRawPageMetadataQuery(config), { options: { apiVersion: config.apiVersion, perspective }, }); diff --git a/src/next.ts b/src/next.ts index 37d1c07..da864bc 100644 --- a/src/next.ts +++ b/src/next.ts @@ -1,7 +1,7 @@ import { FilteredResponseQueryOptions, SanityClient } from 'next-sanity'; import { getAllPageMetadata } from './helpers/page-tree'; -import { getRawPageMetadataQuery } from './queries'; +import { getAllRawPageMetadataQuery } from './queries'; import { PageMetadata, PageTreeConfig } from './types'; export type { PageMetadata } from './types'; @@ -29,7 +29,7 @@ class NextPageTreeClient { public async getAllPageMetadata(): Promise { const rawPageMetadata = await this.client.fetch( - getRawPageMetadataQuery(this.config), + getAllRawPageMetadataQuery(this.config), undefined, this.defaultSanityFetchOptions ?? {}, ); diff --git a/src/queries/index.ts b/src/queries/index.ts index 7b74a6d..fbd2185 100644 --- a/src/queries/index.ts +++ b/src/queries/index.ts @@ -1,18 +1,23 @@ import { getLanguageFieldName } from '../helpers/config'; import { PageTreeConfig } from '../types'; -export const getRawPageMetadataQuery = (config: PageTreeConfig) => `*[_type in [${Object.values(config.pageSchemaTypes) +export const getAllRawPageMetadataQuery = (config: PageTreeConfig) => `*[_type in [${Object.values( + config.pageSchemaTypes, +) .map(key => `"${key}"`) .join(', ')}]]{ + ${rawPageMetadataFragment(config)} + }`; + +export const getRawPageMetadataQuery = (documentId: string, config: PageTreeConfig) => `*[_id == "${documentId}"]{ + ${rawPageMetadataFragment(config)} +}`; + +export const rawPageMetadataFragment = (config: PageTreeConfig) => ` _id, _type, _updatedAt, parent, slug, title, - ${getLanguageFieldName(config) ?? ''} - }`; - -export const getDocumentTypeQuery = (documentId: string) => `*[_id == "${documentId}"]{ - _type -}`; + ${getLanguageFieldName(config) ?? ''}`; diff --git a/src/types.ts b/src/types.ts index d9897bc..42b8eda 100644 --- a/src/types.ts +++ b/src/types.ts @@ -60,6 +60,8 @@ export type PageTreeConfig = { supportedLanguages: string[]; /* Optional field name of the language field, defaults to "language" */ languageFieldName?: string; + /* Adds validation check to ensure that the language of the document matches the language of the parent document. Default: false */ + documentLanguageShouldMatchParent?: boolean; }; }; diff --git a/src/validators/parent-validator.ts b/src/validators/parent-validator.ts index 8ec849e..b273dd2 100644 --- a/src/validators/parent-validator.ts +++ b/src/validators/parent-validator.ts @@ -1,6 +1,7 @@ import { Reference, ValidationContext } from 'sanity'; -import { getDocumentTypeQuery } from '../queries'; +import { getLanguageFieldName } from '../helpers/config'; +import { getRawPageMetadataQuery } from '../queries'; import { PageTreeConfig, RawPageMetadata, SanityRef } from '../types'; /** @@ -8,13 +9,9 @@ import { PageTreeConfig, RawPageMetadata, SanityRef } from '../types'; */ export const allowedParentValidator = (config: PageTreeConfig, ownType: string) => - async (selectedParent: Reference | undefined, context: ValidationContext) => { + async (selectedParentRef: Reference | undefined, context: ValidationContext) => { const allowedParents = config.allowedParents?.[ownType]; - if (allowedParents === undefined) { - return true; - } - const parentRef = context.document?.parent as SanityRef | undefined; if (!parentRef) { return true; @@ -27,15 +24,24 @@ export const allowedParentValidator = } const client = context.getClient({ apiVersion: config.apiVersion }); - const selectedParentType = (await client.fetch[]>(getDocumentTypeQuery(parentId)))[0] - ?._type; + const selectedParent = (await client.fetch(getRawPageMetadataQuery(parentId, config)))?.[0]; - if (!selectedParentType) { + if (!selectedParent._type) { return 'Unable to check the type of the selected parent.'; } - if (!allowedParents.includes(selectedParentType)) { - return `The parent of type "${selectedParentType}" is not allowed for this type of document.`; + if (allowedParents && !allowedParents.includes(selectedParent._type)) { + return `The parent of type "${selectedParent._type}" is not allowed for this type of document.`; + } + + if (config.documentInternationalization?.documentLanguageShouldMatchParent) { + const languageFieldName = getLanguageFieldName(config); + const language = context.document?.[languageFieldName]; + const parentLanguage = selectedParent?.[languageFieldName]; + + if (language !== parentLanguage) { + return 'The language of the parent must match the language of the document.'; + } } return true; diff --git a/src/validators/slug-validator.ts b/src/validators/slug-validator.ts index a1dc818..350f749 100644 --- a/src/validators/slug-validator.ts +++ b/src/validators/slug-validator.ts @@ -1,7 +1,7 @@ import { SlugValue, ValidationContext } from 'sanity'; import { DRAFTS_PREFIX } from '../helpers/page-tree'; -import { getRawPageMetadataQuery } from '../queries'; +import { getAllRawPageMetadataQuery } from '../queries'; import { PageTreeConfig, RawPageMetadata, SanityRef } from '../types'; import { getSanityDocumentId } from '../utils/sanity'; @@ -17,7 +17,7 @@ export const slugValidator = return true; } - const allPages = await client.fetch(getRawPageMetadataQuery(config)); + const allPages = await client.fetch(getAllRawPageMetadataQuery(config)); const siblingPages = allPages.filter(page => page.parent?._ref === parentRef._ref); const siblingPagesWithSameSlug = siblingPages