@ai-growth/nextjs
Version:
Seamlessly integrate Sanity CMS with Next.js applications for automated blog routing and rendering
441 lines • 11.4 kB
TypeScript
/**
* @fileoverview TypeScript interfaces for Sanity CMS document types
*
* This module provides comprehensive type definitions for Sanity documents,
* including base types, content types, and utility types for GROQ queries.
*
* @example
* ```typescript
* import { SanityPost, SanityPage } from '@ai-growth/nextjs/types';
*
* const post: SanityPost = {
* _id: 'post-123',
* _type: 'post',
* title: 'My Blog Post',
* slug: { current: 'my-blog-post' },
* // ... other fields
* };
* ```
*/
/**
* Base interface for all Sanity documents.
* Every document in Sanity extends this base structure.
*/
export interface SanityDocument {
/** Unique document identifier */
_id: string;
/** Document type identifier matching the schema */
_type: string;
/** ISO timestamp when document was created */
_createdAt: string;
/** ISO timestamp when document was last updated */
_updatedAt: string;
/** Document revision identifier for optimistic locking */
_rev: string;
}
/**
* Generic base interface for extending with specific document types
*
* @template T Additional fields for the specific document type
*
* @example
* ```typescript
* interface CustomPost extends SanityDocumentBase<{
* title: string;
* content: string;
* }> {
* _type: 'customPost';
* }
* ```
*/
export type SanityDocumentBase<T = Record<string, unknown>> = SanityDocument & T;
/**
* Reference to another Sanity document
*
* @template T The type of document being referenced
*/
export interface SanityReference<T extends SanityDocument = SanityDocument> {
_type: 'reference';
_ref: string;
/** Weak reference that won't prevent document deletion */
_weak?: boolean;
/** Referenced document data (when populated in queries) */
_referenceData?: T;
}
/**
* Sanity slug field structure
*/
export interface SanitySlug {
_type: 'slug';
/** Current slug value */
current: string;
/** Source field used to generate the slug */
source?: string;
}
/**
* Sanity image asset reference
*/
export interface SanityImageAsset extends SanityDocument {
_type: 'sanity.imageAsset';
url: string;
/** Original filename */
originalFilename?: string;
/** File size in bytes */
size?: number;
/** Image dimensions */
metadata?: {
dimensions: {
width: number;
height: number;
aspectRatio: number;
};
/** EXIF data and other metadata */
[key: string]: unknown;
};
}
/**
* Sanity image field with asset reference and optional metadata
*/
export interface SanityImage {
_type: 'image';
/** Reference to image asset */
asset: SanityReference<SanityImageAsset>;
/** Alternative text for accessibility */
alt?: string;
/** Image caption */
caption?: string;
/** Crop coordinates */
crop?: {
top: number;
bottom: number;
left: number;
right: number;
};
/** Hotspot for responsive cropping */
hotspot?: {
x: number;
y: number;
height: number;
width: number;
};
/** Custom metadata */
[key: string]: unknown;
}
/**
* Sanity file asset reference
*/
export interface SanityFileAsset extends SanityDocument {
_type: 'sanity.fileAsset';
url: string;
/** Original filename */
originalFilename?: string;
/** File size in bytes */
size?: number;
/** MIME type */
mimeType?: string;
}
/**
* Sanity file field with asset reference
*/
export interface SanityFile {
_type: 'file';
/** Reference to file asset */
asset: SanityReference<SanityFileAsset>;
/** File title or description */
title?: string;
}
/**
* Base block content structure for Sanity's Portable Text
*/
export interface SanityBlock {
_type: 'block';
_key: string;
/** Block style (e.g., 'normal', 'h1', 'h2', etc.) */
style?: string;
/** List item information */
listItem?: string;
/** List nesting level */
level?: number;
/** Array of inline content (spans, inline objects) */
children: SanitySpan[];
/** Block-level marks/annotations */
markDefs?: SanityMarkDef[];
}
/**
* Inline text span within a block
*/
export interface SanitySpan {
_type: 'span';
_key: string;
/** The actual text content */
text: string;
/** Applied text marks (bold, italic, links, etc.) */
marks?: string[];
}
/**
* Mark definition for text annotations (links, custom marks)
*/
export interface SanityMarkDef {
_type: string;
_key: string;
/** Additional properties based on mark type */
[key: string]: unknown;
}
/**
* Link mark definition
*/
export interface SanityLinkMark extends SanityMarkDef {
_type: 'link';
href: string;
/** Open link in new tab */
blank?: boolean;
}
/**
* Array of portable text content (blocks and inline objects)
*/
export type SanityPortableText = Array<SanityBlock | SanityCustomBlock>;
/**
* Custom block object (images, videos, custom components)
*/
export interface SanityCustomBlock {
_type: string;
_key: string;
/** Additional properties based on block type */
[key: string]: unknown;
}
/**
* SEO metadata structure
*/
export interface SanitySEO {
/** Page title for search engines */
title?: string;
/** Meta description */
description?: string;
/** Canonical URL */
canonical?: string;
/** Open Graph image */
image?: SanityImage;
/** Additional meta tags */
keywords?: string[];
/** Robots directive */
noIndex?: boolean;
/** Prevent following links */
noFollow?: boolean;
}
/**
* Author/User document
*/
export interface SanityAuthor extends SanityDocument {
_type: 'author';
/** Author's full name */
name: string;
/** URL-friendly identifier */
slug: SanitySlug;
/** Author profile image */
image?: SanityImage;
/** Short biography */
bio?: SanityPortableText;
/** Email address */
email?: string;
/** Website URL */
website?: string;
/** Social media links */
social?: {
twitter?: string;
linkedin?: string;
github?: string;
[platform: string]: string | undefined;
};
}
/**
* Category/Tag document for content organization
*/
export interface SanityCategory extends SanityDocument {
_type: 'category';
/** Category name */
title: string;
/** URL-friendly identifier */
slug: SanitySlug;
/** Category description */
description?: string;
/** Category color for UI */
color?: string;
/** Parent category for hierarchical organization */
parent?: SanityReference<SanityCategory>;
}
/**
* Blog post document
*/
export interface SanityPost extends SanityDocument {
_type: 'post';
/** Post title */
title: string;
/** URL-friendly identifier */
slug: SanitySlug;
/** Post excerpt/summary */
excerpt?: string;
/** Featured image */
mainImage?: SanityImage;
/** Post content in Portable Text format */
body?: SanityPortableText;
/** Post author */
author?: SanityReference<SanityAuthor>;
/** Post categories */
categories?: SanityReference<SanityCategory>[];
/** Publication date */
publishedAt?: string;
/** Featured post flag */
featured?: boolean;
/** Post status */
status?: 'draft' | 'published' | 'archived';
/** SEO metadata */
seo?: SanitySEO;
/** Estimated reading time in minutes */
readingTime?: number;
}
/**
* Static page document
*/
export interface SanityPage extends SanityDocument {
_type: 'page';
/** Page title */
title: string;
/** URL-friendly identifier */
slug: SanitySlug;
/** Page content in Portable Text format */
body?: SanityPortableText;
/** Featured image */
mainImage?: SanityImage;
/** Page template/layout identifier */
template?: string;
/** Parent page for hierarchical organization */
parent?: SanityReference<SanityPage>;
/** Page order for navigation */
order?: number;
/** Show in navigation menu */
showInNavigation?: boolean;
/** SEO metadata */
seo?: SanitySEO;
/** Page status */
status?: 'draft' | 'published' | 'archived';
}
/**
* Navigation menu document
*/
export interface SanityNavigation extends SanityDocument {
_type: 'navigation';
/** Menu title/identifier */
title: string;
/** Menu items */
items: SanityNavigationItem[];
}
/**
* Navigation menu item
*/
export interface SanityNavigationItem {
_type: 'navigationItem';
_key: string;
/** Menu item label */
title: string;
/** Link URL */
url?: string;
/** Internal page reference */
page?: SanityReference<SanityPage>;
/** External link flag */
external?: boolean;
/** Open in new tab */
newTab?: boolean;
/** Nested menu items */
children?: SanityNavigationItem[];
}
/**
* Site settings document
*/
export interface SanitySiteSettings extends SanityDocument {
_type: 'siteSettings';
/** Site title */
title: string;
/** Site description */
description: string;
/** Site logo */
logo?: SanityImage;
/** Site favicon */
favicon?: SanityImage;
/** Default SEO settings */
defaultSeo?: SanitySEO;
/** Social media links */
social?: {
[platform: string]: string;
};
/** Contact information */
contact?: {
email?: string;
phone?: string;
address?: string;
};
/** Google Analytics tracking ID */
googleAnalyticsId?: string;
}
/**
* Union type of all document types for type-safe queries
*/
export type SanityDocumentType = SanityPost | SanityPage | SanityAuthor | SanityCategory | SanityNavigation | SanitySiteSettings;
/**
* Extract document type string from document interfaces
*/
export type SanityDocumentTypeName = SanityDocumentType['_type'];
/**
* Utility type for GROQ query results with projection
*
* @template T The base document type
* @template P The projected fields
*/
export type SanityProjection<T, P extends keyof T> = Pick<T, P>;
/**
* Common projection for list views (id, type, title, slug)
*/
export type SanityListItem<T extends SanityDocument> = SanityProjection<T, '_id' | '_type'> & {
title?: string;
slug?: SanitySlug;
};
/**
* Query result with pagination metadata
*/
export interface SanityQueryResult<T> {
/** Query results */
documents: T[];
/** Total number of documents (if requested) */
total?: number;
/** Pagination offset */
offset?: number;
/** Page size limit */
limit?: number;
}
/**
* Error structure for Sanity API responses
*/
export interface SanityError {
message: string;
statusCode?: number;
details?: unknown;
}
/**
* Query parameters for GROQ queries
*/
export interface SanityQueryParams {
[key: string]: string | number | boolean | null | undefined;
}
/**
* Options for Sanity client fetch operations
*/
export interface SanityFetchOptions {
/** Query parameters for GROQ variables */
params?: SanityQueryParams;
/** Use CDN for faster response */
useCdn?: boolean;
/** Request timeout in milliseconds */
timeout?: number;
/** Additional request headers */
headers?: Record<string, string>;
}
//# sourceMappingURL=sanity.d.ts.map