@invisiblecities/sanity-edge-fetcher
Version:
Lightweight, Edge Runtime-compatible Sanity client for Next.js and Vercel Edge Functions
139 lines (135 loc) • 5.61 kB
TypeScript
/**
* @file stega.ts
* @description Stega encoding support for visual editing with optional @vercel/stega dependency
* @author Invisible Cities Agency
* @license MIT
*/
/**
* Stega configuration options
*/
interface StegaConfig {
enabled: boolean;
studioUrl?: string;
basePath?: string;
filter?: (path: string) => boolean;
projectId?: string;
dataset?: string;
}
/**
* Check if stega should be enabled
*/
declare function shouldEnableStega(isDraftMode: boolean, config?: Partial<StegaConfig>): boolean;
/**
* Build stega configuration from environment and options
*/
declare function buildStegaConfig(isDraftMode: boolean, options?: Partial<StegaConfig>): StegaConfig;
/**
* Clean stega-encoded strings (remove invisible characters)
* Useful for comparing values or using in business logic
*/
declare function stegaClean<T = any>(value: T): T;
/**
* @file core.ts
* @description Next.js-native, edge-compatible Sanity data fetcher with stega support
* @author Invisible Cities Agency
* @license MIT
*/
declare function detectStegaRequest(options?: {
/** Feature flag cookie name set by Studio or a toggle endpoint (default: 'ic_stega') */
cookieName?: string;
/** Optional custom header to allow one-shot enablement (default checks common names) */
headerName?: string;
/** Studio URL or origin to validate Referer against; defaults to NEXT_PUBLIC_SANITY_STUDIO_URL */
studioUrl?: string;
/** Force enable regardless of environment signals */
forceEnable?: boolean;
/** Force disable regardless of environment signals */
forceDisable?: boolean;
}): Promise<boolean>;
type QueryParams = Record<string, string | number | boolean | null | undefined | Array<string | number | boolean>>;
interface EdgeSanityFetchOptions {
/** Sanity dataset to query (e.g., 'production', 'staging') */
dataset: string;
/** GROQ query string */
query: string;
/** Optional query parameters for GROQ placeholders */
params?: QueryParams;
/** Whether to use Sanity's CDN (faster but no auth) */
useCdn?: boolean;
/** Whether to include auth token for draft preview access */
useAuth?: boolean;
/** Stega configuration for visual editing */
stega?: Partial<StegaConfig>;
}
/**
* Fetches data from Sanity using native fetch API
* Compatible with Edge Runtime and static generation
*/
declare function edgeSanityFetch<T>({ dataset, query, params, useCdn, useAuth, stega }: EdgeSanityFetchOptions): Promise<T>;
/**
* Factory function to create a typed Sanity fetcher for a given dataset
*/
declare function createEdgeSanityFetcher(dataset: string, useAuth?: boolean, stega?: Partial<StegaConfig>): <T>(query: string, params?: QueryParams) => Promise<T>;
/**
* Next.js-aware Sanity fetcher that automatically handles draft mode
* This is the primary fetcher for Next.js applications
*
* @example
* const data = await sanityFetch('*[_type == "post"][0]');
*/
declare function sanityFetch<T = unknown>(query: string, params?: QueryParams, options?: {
dataset?: string;
/** Override automatic draft mode detection */
forceAuth?: boolean;
/** Stega configuration for visual editing */
stega?: Partial<StegaConfig>;
}): Promise<T>;
/**
* Presentation-aware hybrid fetcher
* Automatically enables authenticated fetch + stega overlays when a Studio/Presentation
* signal is detected (draftMode cookie, feature flag cookie, referer from Studio, or header).
* Otherwise uses fast CDN fetch with no stega.
*/
declare function sanityFetchHybrid<T = unknown>(query: string, params?: QueryParams, options?: {
dataset?: string;
/** Optional stega options to merge with defaults */
stega?: Partial<StegaConfig>;
/** Detection overrides */
cookieName?: string;
headerName?: string;
studioUrl?: string;
forceEnableStega?: boolean;
forceDisableStega?: boolean;
}): Promise<T>;
/**
* Sanity fetcher with automatic draft fallback
* Tries to fetch published content first, falls back to drafts if empty
* Perfect for singleton documents that might only exist as drafts
*
* @example
* const page = await sanityFetchWithFallback('*[_type == "page" && slug.current == $slug][0]', { slug });
*/
declare function sanityFetchWithFallback<T = unknown>(query: string, params?: QueryParams, options?: {
dataset?: string;
/** Log when falling back to drafts */
logFallback?: boolean;
/** Stega configuration for visual editing */
stega?: Partial<StegaConfig>;
}): Promise<T>;
/**
* Static content fetcher - always uses CDN, never authenticates
* Use for global settings and content that rarely changes
*
* @example
* const settings = await sanityFetchStatic('*[_type == "siteSettings"][0]');
*/
declare function sanityFetchStatic<T = unknown>(query: string, params?: QueryParams, dataset?: string): Promise<T>;
/**
* Authenticated fetcher - always uses authentication
* Use when you need to ensure draft content is visible
*
* @example
* const drafts = await sanityFetchAuthenticated('*[_type == "post" && _id in path("drafts.**")]');
*/
declare function sanityFetchAuthenticated<T = unknown>(query: string, params?: QueryParams, dataset?: string): Promise<T>;
export { type EdgeSanityFetchOptions as E, type QueryParams as Q, type StegaConfig as S, sanityFetchWithFallback as a, sanityFetchStatic as b, sanityFetchAuthenticated as c, sanityFetchHybrid as d, detectStegaRequest as e, edgeSanityFetch as f, createEdgeSanityFetcher as g, buildStegaConfig as h, shouldEnableStega as i, stegaClean as j, sanityFetch as s };