strapi-nextgen-framework
Version:
Production-ready, type-safe framework bridging Strapi v4 CMS and Next.js 14+ App Router with automatic cache management, Error Boundaries, and SEO optimization
80 lines • 3.55 kB
JavaScript
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import { ComponentErrorBoundary } from './error-boundary';
import { validateComponentData } from './validator';
/**
* Renders Strapi dynamic zones with automatic component mapping
*
* Features:
* - Automatic Error Boundary wrapping for each component
* - Optional Zod validation in development mode
* - Graceful degradation in production
* - Type-safe component mapping
*
* @param props - Renderer configuration
*
* @example
* ```tsx
* <StrapiRenderer
* data={dynamicZoneData}
* map={componentMap}
* validation="warn"
* />
* ```
*/
export function StrapiRenderer(props) {
const { data, map, validation = process.env.NODE_ENV === 'development' ? 'error' : 'silent', fallback, onError, } = props;
// Handle empty or invalid data
if (!data || !Array.isArray(data)) {
if (process.env.NODE_ENV === 'development') {
console.warn('[StrapiRenderer] Invalid data prop: expected array, got:', typeof data);
}
return fallback ? _jsx(_Fragment, { children: fallback }) : _jsx(_Fragment, {});
}
// Handle empty array
if (data.length === 0) {
return fallback ? _jsx(_Fragment, { children: fallback }) : _jsx(_Fragment, {});
}
return (_jsx(_Fragment, { children: data.map((item, index) => {
// Type guard: ensure item is an object
if (typeof item !== 'object' || item === null) {
if (process.env.NODE_ENV === 'development') {
console.error('[StrapiRenderer] Invalid component data:', item);
}
return null;
}
const component = item;
// Extract component type from __component field
const componentType = component.__component;
if (typeof componentType !== 'string') {
if (process.env.NODE_ENV === 'development') {
console.error('[StrapiRenderer] Component missing __component field:', component);
}
return null;
}
// Look up component in map
const mapEntry = map[componentType];
if (!mapEntry) {
if (process.env.NODE_ENV === 'development') {
console.error(`[StrapiRenderer] No component mapped for type: ${componentType}`, '\nAvailable mappings:', Object.keys(map));
}
return null;
}
const { component: Component, schema } = mapEntry;
// Validate component data with Zod schema (if provided)
if (schema && validation !== 'silent') {
const validationResult = validateComponentData(component, schema, componentType, validation);
// If validation failed and mode is 'error', skip rendering
if (!validationResult.success && validation === 'error') {
return null;
}
}
// Generate unique key for component
const componentId = component.id;
const key = (typeof componentId === 'string' || typeof componentId === 'number')
? componentId
: `${componentType}-${index}`;
// Render component wrapped in Error Boundary
return (_jsx(ComponentErrorBoundary, { componentType: componentType, onError: onError, fallback: fallback, children: _jsx(Component, { ...component }) }, key));
}) }));
}
//# sourceMappingURL=index.js.map