UNPKG

resolvo-cms

Version:

Headless CMS for Resolvo websites with real-time content management

3,171 lines 114 kB
import axios from 'axios';
import { io } from 'socket.io-client';
import { z } from 'zod';
import require$$0, { useState, useRef, useEffect, useCallback, Component } from 'react';

class ContentCache {
    constructor(cleanupIntervalMs = 60000) {
        this.cleanupIntervalMs = cleanupIntervalMs;
        this.cache = new Map();
        this.cleanupInterval = null;
        this.defaultTTL = 5 * 60 * 1000; // 5 minutes
        this.maxSize = 1000; // Prevent memory leaks
        this.startCleanupInterval();
    }
    get(key) {
        const item = this.cache.get(key);
        if (!item)
            return null;
        if (this.isExpired(item)) {
            this.cache.delete(key);
            return null;
        }
        return item.data;
    }
    set(key, data, ttl = this.defaultTTL) {
        // Implement LRU-like behavior when cache is full
        if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
            this.evictOldest();
        }
        this.cache.set(key, {
            data,
            timestamp: Date.now(),
            ttl
        });
    }
    delete(key) {
        return this.cache.delete(key);
    }
    clear() {
        this.cache.clear();
    }
    has(key) {
        const item = this.cache.get(key);
        if (!item)
            return false;
        if (this.isExpired(item)) {
            this.cache.delete(key);
            return false;
        }
        return true;
    }
    size() {
        return this.cache.size;
    }
    isExpired(item) {
        return Date.now() - item.timestamp > item.ttl;
    }
    evictOldest() {
        let oldestKey = null;
        let oldestTime = Date.now();
        for (const [key, item] of this.cache.entries()) {
            if (item.timestamp < oldestTime) {
                oldestTime = item.timestamp;
                oldestKey = key;
            }
        }
        if (oldestKey) {
            this.cache.delete(oldestKey);
        }
    }
    startCleanupInterval() {
        if (this.cleanupInterval) {
            clearInterval(this.cleanupInterval);
        }
        this.cleanupInterval = setInterval(() => {
            this.cleanup();
        }, this.cleanupIntervalMs);
    }
    cleanup() {
        for (const [key, item] of this.cache.entries()) {
            if (this.isExpired(item)) {
                this.cache.delete(key);
            }
        }
    }
    destroy() {
        if (this.cleanupInterval) {
            clearInterval(this.cleanupInterval);
            this.cleanupInterval = null;
        }
        this.cache.clear();
    }
}
class SchemaCache extends ContentCache {
    constructor() {
        super(...arguments);
        this.fieldCache = new Map();
    }
    getField(schemaId, fieldName) {
        const schemaFields = this.fieldCache.get(schemaId);
        if (!schemaFields)
            return null;
        return schemaFields.get(fieldName) || null;
    }
    setField(schemaId, fieldName, data) {
        if (!this.fieldCache.has(schemaId)) {
            this.fieldCache.set(schemaId, new Map());
        }
        this.fieldCache.get(schemaId).set(fieldName, data);
    }
    clearSchema(schemaId) {
        this.fieldCache.delete(schemaId);
    }
}
class LRUCache {
    constructor(capacity = 100) {
        this.cache = new Map();
        this.capacity = capacity;
    }
    get(key) {
        const item = this.cache.get(key);
        if (!item)
            return null;
        // Update timestamp for LRU
        this.cache.delete(key);
        this.cache.set(key, { value: item.value, timestamp: Date.now() });
        return item.value;
    }
    set(key, value) {
        if (this.cache.has(key)) {
            this.cache.delete(key);
        }
        else if (this.cache.size >= this.capacity) {
            // Remove oldest item
            const oldestKey = this.cache.keys().next().value;
            if (oldestKey) {
                this.cache.delete(oldestKey);
            }
        }
        this.cache.set(key, { value, timestamp: Date.now() });
    }
    delete(key) {
        return this.cache.delete(key);
    }
    clear() {
        this.cache.clear();
    }
    size() {
        return this.cache.size;
    }
}

class ValidationError extends Error {
    constructor(message, field, value, rule) {
        super(message);
        this.field = field;
        this.value = value;
        this.rule = rule;
        this.name = 'ValidationError';
    }
}
function validateField(field, value) {
    const errors = [];
    if (!field.validation) {
        return { isValid: true, errors: [] };
    }
    for (const rule of field.validation) {
        const error = validateRule(field, value, rule);
        if (error) {
            errors.push(error);
        }
    }
    return {
        isValid: errors.length === 0,
        errors
    };
}
function validateRule(field, value, rule) {
    switch (rule.type) {
        case 'required':
            if (value === null || value === undefined || value === '') {
                return new ValidationError(rule.message || `${field.label} is required`, field.name, value, rule);
            }
            break;
        case 'min':
            if (field.type === 'number' && typeof value === 'number') {
                if (value < rule.value) {
                    return new ValidationError(rule.message || `${field.label} must be at least ${rule.value}`, field.name, value, rule);
                }
            }
            else if (typeof value === 'string') {
                if (value.length < rule.value) {
                    return new ValidationError(rule.message || `${field.label} must be at least ${rule.value} characters`, field.name, value, rule);
                }
            }
            break;
        case 'max':
            if (field.type === 'number' && typeof value === 'number') {
                if (value > rule.value) {
                    return new ValidationError(rule.message || `${field.label} must be at most ${rule.value}`, field.name, value, rule);
                }
            }
            else if (typeof value === 'string') {
                if (value.length > rule.value) {
                    return new ValidationError(rule.message || `${field.label} must be at most ${rule.value} characters`, field.name, value, rule);
                }
            }
            break;
        case 'pattern':
            if (typeof value === 'string' && rule.value) {
                const regex = new RegExp(rule.value);
                if (!regex.test(value)) {
                    return new ValidationError(rule.message || `${field.label} format is invalid`, field.name, value, rule);
                }
            }
            break;
        case 'email':
            if (typeof value === 'string' && value) {
                const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
                if (!emailRegex.test(value)) {
                    return new ValidationError(rule.message || `${field.label} must be a valid email address`, field.name, value, rule);
                }
            }
            break;
        case 'url':
            if (typeof value === 'string' && value) {
                try {
                    new URL(value);
                }
                catch {
                    return new ValidationError(rule.message || `${field.label} must be a valid URL`, field.name, value, rule);
                }
            }
            break;
    }
    return null;
}
function validateContent(schema, data) {
    const errors = [];
    // Validate that all required fields are present
    for (const field of schema.fields) {
        const value = data[field.name];
        // Check if field is required but missing
        const isRequired = field.validation?.some(rule => rule.type === 'required');
        if (isRequired && (value === undefined || value === null)) {
            errors.push(new ValidationError(`${field.label || field.name} is required`, field.name, value, { type: 'required', message: `${field.label || field.name} is required` }));
            continue;
        }
        // Skip validation for undefined/null values unless required
        if (value === undefined || value === null) {
            continue;
        }
        const fieldValidation = validateField(field, value);
        if (!fieldValidation.isValid) {
            errors.push(...fieldValidation.errors);
        }
    }
    return {
        isValid: errors.length === 0,
        errors
    };
}
function createZodSchema(fields) {
    const schemaObject = {};
    for (const field of fields) {
        let fieldSchema;
        switch (field.type) {
            case 'text':
            case 'textarea':
            case 'url':
                fieldSchema = z.string();
                break;
            case 'number':
                fieldSchema = z.number();
                break;
            case 'boolean':
                fieldSchema = z.boolean();
                break;
            case 'date':
                fieldSchema = z.string().datetime();
                break;
            case 'datetime':
                fieldSchema = z.string().datetime();
                break;
            case 'color':
                fieldSchema = z.string().regex(/^#[0-9A-F]{6}$/i);
                break;
            case 'array':
                fieldSchema = z.array(z.any());
                break;
            case 'object':
                fieldSchema = z.record(z.any());
                break;
            default:
                fieldSchema = z.any();
        }
        // Apply validation rules
        if (field.validation) {
            for (const rule of field.validation) {
                switch (rule.type) {
                    case 'required':
                        fieldSchema = fieldSchema;
                        break;
                    case 'min':
                        if (field.type === 'number') {
                            fieldSchema = fieldSchema.min(rule.value);
                        }
                        else {
                            fieldSchema = fieldSchema.min(rule.value);
                        }
                        break;
                    case 'max':
                        if (field.type === 'number') {
                            fieldSchema = fieldSchema.max(rule.value);
                        }
                        else {
                            fieldSchema = fieldSchema.max(rule.value);
                        }
                        break;
                    case 'email':
                        fieldSchema = fieldSchema.email();
                        break;
                    case 'url':
                        fieldSchema = fieldSchema.url();
                        break;
                }
            }
        }
        else if (!field.required) {
            fieldSchema = fieldSchema.optional();
        }
        schemaObject[field.name] = fieldSchema;
    }
    return z.object(schemaObject);
}

function serializeContent(data, fields) {
    const serialized = {};
    for (const field of fields) {
        const value = data[field.name];
        serialized[field.name] = serializeField(value, field.type);
    }
    return serialized;
}
function deserializeContent(data, fields) {
    const deserialized = {};
    for (const field of fields) {
        const value = data[field.name];
        deserialized[field.name] = deserializeField(value, field.type);
    }
    return deserialized;
}
function serializeField(value, type) {
    if (value === null || value === undefined) {
        return value;
    }
    switch (type) {
        case 'date':
        case 'datetime':
            return value instanceof Date ? value.toISOString() : value;
        case 'number':
            return typeof value === 'string' ? parseFloat(value) : value;
        case 'boolean':
            if (typeof value === 'string') {
                return value.toLowerCase() === 'true' || value === '1';
            }
            return Boolean(value);
        case 'array':
            return Array.isArray(value) ? value : [value];
        case 'object':
            return typeof value === 'object' ? value : JSON.parse(value);
        case 'image':
        case 'file':
            return typeof value === 'string' ? value : value?.url || value;
        default:
            return value;
    }
}
function deserializeField(value, type) {
    if (value === null || value === undefined) {
        return value;
    }
    switch (type) {
        case 'date':
        case 'datetime':
            return new Date(value);
        case 'number':
            return typeof value === 'number' ? value : parseFloat(value);
        case 'boolean':
            return Boolean(value);
        case 'array':
            return Array.isArray(value) ? value : [value];
        case 'object':
            return typeof value === 'object' ? value : JSON.parse(value);
        default:
            return value;
    }
}
function formatFieldValue(value, type) {
    if (value === null || value === undefined) {
        return '';
    }
    switch (type) {
        case 'date':
        case 'datetime':
            return value instanceof Date ? value.toLocaleDateString() : value;
        case 'boolean':
            return value ? 'Yes' : 'No';
        case 'array':
            return Array.isArray(value) ? value.join(', ') : String(value);
        case 'object':
            return typeof value === 'object' ? JSON.stringify(value) : String(value);
        case 'image':
        case 'file':
            return typeof value === 'string' ? value : value?.url || 'No file';
        default:
            return String(value);
    }
}
function parseFieldValue(value, type) {
    if (!value) {
        return null;
    }
    switch (type) {
        case 'number':
            return parseFloat(value);
        case 'boolean':
            return value.toLowerCase() === 'true' || value === '1';
        case 'array':
            return value.split(',').map(v => v.trim());
        case 'object':
            try {
                return JSON.parse(value);
            }
            catch {
                return value;
            }
        default:
            return value;
    }
}
function generateFieldId() {
    return Math.random().toString(36).substr(2, 9);
}
function sanitizeFieldName(name) {
    return name
        .toLowerCase()
        .replace(/[^a-z0-9]/g, '_')
        .replace(/_+/g, '_')
        .replace(/^_|_$/g, '');
}

const API_ENDPOINTS = {
    SCHEMAS: '/cms/schemas',
    CONTENT: '/cms/content',
    PUBLIC_CONTENT: '/cms/public/content',
    AUTH: '/cms/auth',
    VALIDATE_TOKEN: '/cms/validate-token',
};
const DEFAULT_CONFIG = {
    apiUrl: 'http://localhost:3000/api',
    projectId: 1,
    timeout: 10000,
    retries: 3,
    reconnectAttempts: 5,
    reconnectDelay: 1000,
};
const FIELD_TYPES = {
    TEXT: 'text',
    TEXTAREA: 'textarea',
    NUMBER: 'number',
    BOOLEAN: 'boolean',
    IMAGE: 'image',
    FILE: 'file',
    SELECT: 'select',
    ARRAY: 'array',
    OBJECT: 'object',
    RICH_TEXT: 'rich-text',
    DATE: 'date',
    DATETIME: 'datetime',
    COLOR: 'color',
    URL: 'url',
};
const VALIDATION_TYPES = {
    REQUIRED: 'required',
    MIN: 'min',
    MAX: 'max',
    PATTERN: 'pattern',
    EMAIL: 'email',
    URL: 'url',
    CUSTOM: 'custom',
};
const REALTIME_EVENTS = {
    CONTENT_UPDATED: 'content:updated',
    CONTENT_CREATED: 'content:created',
    CONTENT_DELETED: 'content:deleted',
    SCHEMA_UPDATED: 'schema:updated',
};
const ERROR_CODES = {
    UNAUTHORIZED: 'UNAUTHORIZED',
    FORBIDDEN: 'FORBIDDEN',
    NOT_FOUND: 'NOT_FOUND',
    VALIDATION_ERROR: 'VALIDATION_ERROR',
    NETWORK_ERROR: 'NETWORK_ERROR',
    TIMEOUT_ERROR: 'TIMEOUT_ERROR',
};

class ResolvoCMSClient {
    constructor(config) {
        this.socket = null;
        this.subscriptions = new Map();
        this.reconnectAttempts = 0;
        this.reconnectTimeout = null;
        this.isConnecting = false;
        this.requestQueue = [];
        this.isProcessingQueue = false;
        // Event handling
        this.eventListeners = new Map();
        this.config = {
            ...DEFAULT_CONFIG,
            ...config
        };
        this.maxReconnectAttempts = this.config.reconnectAttempts ?? DEFAULT_CONFIG.reconnectAttempts;
        this.cache = new ContentCache();
        this.httpClient = axios.create({
            baseURL: this.config.apiUrl,
            timeout: this.config.timeout,
            headers: {
                'Content-Type': 'application/json',
            },
        });
        this.setupInterceptors();
    }
    setupInterceptors() {
        // Request interceptor
        this.httpClient.interceptors.request.use((config) => {
            // Add authentication headers
            if (this.config.websiteToken) {
                config.headers['X-Website-Token'] = this.config.websiteToken;
            }
            if (this.config.authToken) {
                config.headers['Authorization'] = `Bearer ${this.config.authToken}`;
            }
            return config;
        }, (error) => Promise.reject(error));
        // Response interceptor
        this.httpClient.interceptors.response.use((response) => response, async (error) => {
            if (error.response?.status === 401) {
                // Handle authentication errors
                this.handleAuthError();
            }
            return Promise.reject(error);
        });
    }
    handleAuthError() {
        // Clear cache and disconnect socket
        this.cache.clear();
        this.disconnect();
        // Emit auth error event
        this.emit('auth:error', { message: 'Authentication failed' });
    }
    async retryRequest(requestFn, maxRetries = 3, delay = 1000) {
        let lastError;
        for (let attempt = 0; attempt <= maxRetries; attempt++) {
            try {
                return await requestFn();
            }
            catch (error) {
                lastError = error;
                if (attempt === maxRetries) {
                    break;
                }
                // Don't retry on authentication errors
                if (error.response?.status === 401) {
                    break;
                }
                // Exponential backoff
                const backoffDelay = delay * Math.pow(2, attempt);
                await new Promise(resolve => setTimeout(resolve, backoffDelay));
            }
        }
        throw lastError;
    }
    async queueRequest(requestFn) {
        return new Promise((resolve, reject) => {
            this.requestQueue.push(async () => {
                try {
                    const result = await requestFn();
                    resolve(result);
                }
                catch (error) {
                    reject(error);
                }
            });
            this.processQueue();
        });
    }
    async processQueue() {
        if (this.isProcessingQueue || this.requestQueue.length === 0) {
            return;
        }
        this.isProcessingQueue = true;
        while (this.requestQueue.length > 0) {
            const request = this.requestQueue.shift();
            if (request) {
                await request();
            }
        }
        this.isProcessingQueue = false;
    }
    // Schema Management
    async createSchema(schema) {
        return this.retryRequest(async () => {
            const response = await this.httpClient.post(API_ENDPOINTS.SCHEMAS, schema);
            const result = response.data;
            if (!result.success) {
                throw new Error(result.message || 'Failed to create schema');
            }
            // Clear schema cache
            this.cache.delete(`schema:${result.data.id}`);
            return result.data;
        });
    }
    async getSchema(schemaId) {
        // Check cache first
        const cached = this.cache.get(`schema:${schemaId}`);
        if (cached)
            return cached;
        return this.retryRequest(async () => {
            const response = await this.httpClient.get(`${API_ENDPOINTS.SCHEMAS}/${schemaId}`);
            const result = response.data;
            if (!result.success) {
                throw new Error(result.message || 'Schema not found');
            }
            // Cache the result
            this.cache.set(`schema:${schemaId}`, result.data);
            return result.data;
        });
    }
    async updateSchema(schemaId, updates) {
        const response = await this.httpClient.put(`${API_ENDPOINTS.SCHEMAS}/${schemaId}`, updates);
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to update schema');
        }
        // Clear cache and emit realtime event
        this.cache.delete(`schema:${schemaId}`);
        this.emitRealtimeEvent(REALTIME_EVENTS.SCHEMA_UPDATED, result.data);
        return result.data;
    }
    async deleteSchema(schemaId) {
        const response = await this.httpClient.delete(`${API_ENDPOINTS.SCHEMAS}/${schemaId}`);
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to delete schema');
        }
        // Clear cache
        this.cache.delete(`schema:${schemaId}`);
    }
    async listSchemas(query) {
        const response = await this.httpClient.get(API_ENDPOINTS.SCHEMAS, { params: query });
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to fetch schemas');
        }
        return result.data;
    }
    // Content Management
    async createContent(content) {
        // Get schema for validation
        const schema = await this.getSchema(content.schemaId);
        // Validate content
        const validation = validateContent(schema, content.data);
        if (!validation.isValid) {
            throw new Error(`Validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
        }
        // Serialize content
        const serializedData = serializeContent(content.data, schema.fields);
        const response = await this.httpClient.post(API_ENDPOINTS.CONTENT, { ...content, data: serializedData });
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to create content');
        }
        // Emit realtime event
        this.emitRealtimeEvent(REALTIME_EVENTS.CONTENT_CREATED, result.data);
        return result.data;
    }
    async getContent(contentId) {
        // Check cache first
        const cached = this.cache.get(`content:${contentId}`);
        if (cached)
            return cached;
        const response = await this.httpClient.get(`${API_ENDPOINTS.CONTENT}/${contentId}`);
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Content not found');
        }
        // Cache the result
        this.cache.set(`content:${contentId}`, result.data);
        return result.data;
    }
    async getContentBySchema(schemaId, options) {
        const query = {
            schemaId,
            projectId: this.config.projectId,
            ...options
        };
        const response = await this.httpClient.get(API_ENDPOINTS.CONTENT, { params: query });
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to fetch content');
        }
        return result.data;
    }
    async updateContent(contentId, updates) {
        // Get current content and schema for validation
        const currentContent = await this.getContent(contentId);
        const schema = await this.getSchema(currentContent.schemaId);
        // Merge updates with current data
        const updatedData = { ...currentContent.data, ...updates.data };
        // Validate content
        const validation = validateContent(schema, updatedData);
        if (!validation.isValid) {
            throw new Error(`Validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
        }
        // Serialize content
        const serializedData = serializeContent(updatedData, schema.fields);
        const response = await this.httpClient.put(`${API_ENDPOINTS.CONTENT}/${contentId}`, { ...updates, data: serializedData });
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to update content');
        }
        // Clear cache and emit realtime event
        this.cache.delete(`content:${contentId}`);
        this.emitRealtimeEvent(REALTIME_EVENTS.CONTENT_UPDATED, result.data);
        return result.data;
    }
    async deleteContent(contentId) {
        const response = await this.httpClient.delete(`${API_ENDPOINTS.CONTENT}/${contentId}`);
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to delete content');
        }
        // Clear cache and emit realtime event
        this.cache.delete(`content:${contentId}`);
        this.emitRealtimeEvent(REALTIME_EVENTS.CONTENT_DELETED, { id: contentId });
    }
    async publishContent(contentId) {
        const response = await this.httpClient.post(`${API_ENDPOINTS.CONTENT}/${contentId}/publish`);
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to publish content');
        }
        // Clear cache and emit realtime event
        this.cache.delete(`content:${contentId}`);
        this.emitRealtimeEvent(REALTIME_EVENTS.CONTENT_UPDATED, result.data);
        return result.data;
    }
    // Public API (for websites)
    async getPublicContent(schemaId) {
        const response = await this.httpClient.get(`${API_ENDPOINTS.PUBLIC_CONTENT}/${this.config.projectId}`, {
            params: { schemaId, isPublished: true },
            headers: {
                'X-Website-Token': this.config.websiteToken
            }
        });
        const result = response.data;
        if (!result.success) {
            throw new Error(result.message || 'Failed to fetch public content');
        }
        return result.data;
    }
    // Real-time Features
    connect(wsConfig) {
        if (this.socket?.connected || this.isConnecting) {
            return;
        }
        this.isConnecting = true;
        const wsUrl = wsConfig?.url || this.config.apiUrl.replace('http', 'ws');
        this.socket = io(wsUrl, {
            auth: {
                token: this.config.authToken || this.config.websiteToken
            },
            reconnectionAttempts: this.maxReconnectAttempts,
            reconnectionDelay: this.config.reconnectDelay,
            reconnectionDelayMax: 5000,
            timeout: 20000,
            forceNew: true
        });
        this.socket.on('connect', () => {
            this.reconnectAttempts = 0;
            this.isConnecting = false;
            this.emit('connected');
            // Resubscribe to all subscriptions
            this.resubscribeAll();
        });
        this.socket.on('disconnect', (reason) => {
            this.isConnecting = false;
            this.emit('disconnected', { reason });
            if (reason === 'io server disconnect') {
                // Server disconnected us, don't reconnect
                return;
            }
        });
        this.socket.on('connect_error', (error) => {
            this.isConnecting = false;
            this.reconnectAttempts++;
            this.emit('connection_error', error);
        });
        // Handle real-time events
        Object.values(REALTIME_EVENTS).forEach(event => {
            this.socket.on(event, (data) => {
                this.handleRealtimeEvent(event, data);
            });
        });
    }
    disconnect() {
        if (this.socket) {
            this.socket.disconnect();
            this.socket = null;
        }
    }
    subscribe(schemaId, callback) {
        if (!this.subscriptions.has(schemaId)) {
            this.subscriptions.set(schemaId, []);
        }
        this.subscriptions.get(schemaId).push(callback);
        // Subscribe to real-time updates
        if (this.socket?.connected) {
            this.socket.emit('subscribe:content', { schemaId });
        }
    }
    unsubscribe(schemaId, callback) {
        if (!callback) {
            this.subscriptions.delete(schemaId);
        }
        else {
            const callbacks = this.subscriptions.get(schemaId);
            if (callbacks) {
                const index = callbacks.indexOf(callback);
                if (index > -1) {
                    callbacks.splice(index, 1);
                }
                if (callbacks.length === 0) {
                    this.subscriptions.delete(schemaId);
                }
            }
        }
    }
    handleRealtimeEvent(event, data) {
        const message = {
            type: event,
            data,
            timestamp: new Date()
        };
        // Notify subscribers
        if (data.schemaId && this.subscriptions.has(data.schemaId)) {
            const callbacks = this.subscriptions.get(data.schemaId);
            callbacks.forEach(callback => callback(message));
        }
        // Emit general event
        this.emit(event, message);
    }
    emitRealtimeEvent(event, data) {
        if (this.socket?.connected) {
            this.socket.emit(event, data);
        }
    }
    resubscribeAll() {
        // Resubscribe to all active subscriptions
        for (const [schemaId] of this.subscriptions) {
            if (this.socket?.connected) {
                this.socket.emit('subscribe:content', { schemaId });
            }
        }
    }
    on(event, callback) {
        if (!this.eventListeners.has(event)) {
            this.eventListeners.set(event, []);
        }
        this.eventListeners.get(event).push(callback);
    }
    off(event, callback) {
        const listeners = this.eventListeners.get(event);
        if (listeners) {
            const index = listeners.indexOf(callback);
            if (index > -1) {
                listeners.splice(index, 1);
            }
        }
    }
    emit(event, data) {
        const listeners = this.eventListeners.get(event);
        if (listeners) {
            listeners.forEach(callback => callback(data));
        }
    }
    // Utility methods
    clearCache() {
        this.cache.clear();
    }
    getCacheStats() {
        return {
            size: this.cache.size()
        };
    }
    isConnected() {
        return this.socket?.connected || false;
    }
}

function useContent(client, options = {}) {
    const { schemaId, contentId, isPublished = true, autoConnect = true, realtime = true } = options;
    const [content, setContent] = useState(null);
    const [contentList, setContentList] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [isInitialized, setIsInitialized] = useState(false);
    useRef(client);
    useRef(options);
    const abortControllerRef = useRef(null);
    // Initialize and fetch content
    useEffect(() => {
        if (!client || isInitialized)
            return;
        // Cancel previous request if still pending
        if (abortControllerRef.current) {
            abortControllerRef.current.abort();
        }
        abortControllerRef.current = new AbortController();
        const initialize = async () => {
            try {
                setLoading(true);
                setError(null);
                if (autoConnect && realtime) {
                    client.connect();
                }
                if (contentId) {
                    const contentData = await client.getContent(contentId);
                    if (!abortControllerRef.current?.signal.aborted) {
                        setContent(contentData);
                    }
                }
                else if (schemaId) {
                    const contentData = await client.getContentBySchema(schemaId, { isPublished });
                    if (!abortControllerRef.current?.signal.aborted) {
                        setContentList(contentData);
                    }
                }
                if (!abortControllerRef.current?.signal.aborted) {
                    setIsInitialized(true);
                }
            }
            catch (err) {
                if (!abortControllerRef.current?.signal.aborted) {
                    setError(err instanceof Error ? err : new Error('Failed to fetch content'));
                }
            }
            finally {
                if (!abortControllerRef.current?.signal.aborted) {
                    setLoading(false);
                }
            }
        };
        initialize();
        // Cleanup function
        return () => {
            if (abortControllerRef.current) {
                abortControllerRef.current.abort();
            }
        };
    }, [client, contentId, schemaId, isPublished, autoConnect, realtime, isInitialized]);
    // Real-time updates
    useEffect(() => {
        if (!client || !realtime || !schemaId)
            return;
        const handleContentUpdate = (message) => {
            if (message.type === 'content:updated' || message.type === 'content:created') {
                const updatedContent = message.data;
                if (contentId && updatedContent.id === contentId) {
                    setContent(updatedContent);
                }
                if (schemaId && updatedContent.schemaId === schemaId) {
                    setContentList(prev => {
                        const index = prev.findIndex(c => c.id === updatedContent.id);
                        if (index >= 0) {
                            const newList = [...prev];
                            newList[index] = updatedContent;
                            return newList;
                        }
                        else {
                            return [...prev, updatedContent];
                        }
                    });
                }
            }
            else if (message.type === 'content:deleted') {
                const deletedId = message.data.id;
                if (contentId && deletedId === contentId) {
                    setContent(null);
                }
                setContentList(prev => prev.filter(c => c.id !== deletedId));
            }
        };
        client.subscribe(schemaId, handleContentUpdate);
        return () => {
            client.unsubscribe(schemaId, handleContentUpdate);
        };
    }, [client, schemaId, contentId, realtime]);
    // Content operations
    const createContent = useCallback(async (data) => {
        try {
            setError(null);
            const newContent = await client.createContent(data);
            if (schemaId && newContent.schemaId === schemaId) {
                setContentList(prev => [...prev, newContent]);
            }
            return newContent;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to create content');
            setError(error);
            throw error;
        }
    }, [client, schemaId]);
    const updateContent = useCallback(async (contentId, updates) => {
        try {
            setError(null);
            const updatedContent = await client.updateContent(contentId, updates);
            if (content && content.id === contentId) {
                setContent(updatedContent);
            }
            setContentList(prev => prev.map(c => c.id === contentId ? updatedContent : c));
            return updatedContent;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to update content');
            setError(error);
            throw error;
        }
    }, [client, content]);
    const deleteContent = useCallback(async (contentId) => {
        try {
            setError(null);
            await client.deleteContent(contentId);
            if (content && content.id === contentId) {
                setContent(null);
            }
            setContentList(prev => prev.filter(c => c.id !== contentId));
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to delete content');
            setError(error);
            throw error;
        }
    }, [client, content]);
    const publishContent = useCallback(async (contentId) => {
        try {
            setError(null);
            const publishedContent = await client.publishContent(contentId);
            if (content && content.id === contentId) {
                setContent(publishedContent);
            }
            setContentList(prev => prev.map(c => c.id === contentId ? publishedContent : c));
            return publishedContent;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to publish content');
            setError(error);
            throw error;
        }
    }, [client, content]);
    const refresh = useCallback(async () => {
        try {
            setLoading(true);
            setError(null);
            if (contentId) {
                const contentData = await client.getContent(contentId);
                setContent(contentData);
            }
            else if (schemaId) {
                const contentData = await client.getContentBySchema(schemaId, { isPublished });
                setContentList(contentData);
            }
        }
        catch (err) {
            setError(err instanceof Error ? err : new Error('Failed to refresh content'));
        }
        finally {
            setLoading(false);
        }
    }, [client, contentId, schemaId, isPublished]);
    return {
        content,
        contentList,
        loading,
        error,
        createContent,
        updateContent,
        deleteContent,
        publishContent,
        refresh
    };
}
// Optimistic updates hook
function useOptimisticContent(client, options = {}) {
    const [optimisticData, setOptimisticData] = useState(null);
    const { content, updateContent, ...rest } = useContent(client, options);
    const optimisticUpdate = useCallback(async (contentId, updates) => {
        if (!content) {
            throw new Error('No content to update');
        }
        // Set optimistic data immediately
        const optimisticContent = {
            ...content,
            data: { ...content.data, ...updates.data }};
        setOptimisticData(optimisticContent.data);
        try {
            // Perform actual update
            const result = await updateContent(contentId, updates);
            setOptimisticData(null);
            return result;
        }
        catch (error) {
            // Revert on error
            setOptimisticData(null);
            throw error;
        }
    }, [content, updateContent]);
    return {
        ...rest,
        content: optimisticData ? { ...content, data: optimisticData } : content,
        updateContent: optimisticUpdate
    };
}

function useSchema(client, options = {}) {
    const { schemaId, projectId, isActive = true, autoConnect = true, realtime = true } = options;
    const [schema, setSchema] = useState(null);
    const [schemas, setSchemas] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    const [isInitialized, setIsInitialized] = useState(false);
    // Initialize and fetch schemas
    useEffect(() => {
        if (!client || isInitialized)
            return;
        const initialize = async () => {
            try {
                setLoading(true);
                setError(null);
                if (autoConnect && realtime) {
                    client.connect();
                }
                if (schemaId) {
                    const schemaData = await client.getSchema(schemaId);
                    setSchema(schemaData);
                }
                else {
                    const schemasData = await client.listSchemas({
                        projectId: projectId || client['config'].projectId,
                        isActive
                    });
                    setSchemas(schemasData);
                }
                setIsInitialized(true);
            }
            catch (err) {
                setError(err instanceof Error ? err : new Error('Failed to fetch schemas'));
            }
            finally {
                setLoading(false);
            }
        };
        initialize();
    }, [client, schemaId, projectId, isActive, autoConnect, realtime, isInitialized]);
    // Real-time updates
    useEffect(() => {
        if (!client || !realtime)
            return;
        const handleSchemaUpdate = (message) => {
            if (message.type === 'schema:updated') {
                const updatedSchema = message.data;
                if (schemaId && updatedSchema.id === schemaId) {
                    setSchema(updatedSchema);
                }
                setSchemas(prev => {
                    const index = prev.findIndex(s => s.id === updatedSchema.id);
                    if (index >= 0) {
                        const newList = [...prev];
                        newList[index] = updatedSchema;
                        return newList;
                    }
                    return prev;
                });
            }
        };
        client.on('schema:updated', handleSchemaUpdate);
        return () => {
            client.off('schema:updated', handleSchemaUpdate);
        };
    }, [client, schemaId, realtime]);
    // Schema operations
    const createSchema = useCallback(async (data) => {
        try {
            setError(null);
            const newSchema = await client.createSchema(data);
            setSchemas(prev => [...prev, newSchema]);
            return newSchema;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to create schema');
            setError(error);
            throw error;
        }
    }, [client]);
    const updateSchema = useCallback(async (schemaId, updates) => {
        try {
            setError(null);
            const updatedSchema = await client.updateSchema(schemaId, updates);
            if (schema && schema.id === schemaId) {
                setSchema(updatedSchema);
            }
            setSchemas(prev => prev.map(s => s.id === schemaId ? updatedSchema : s));
            return updatedSchema;
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to update schema');
            setError(error);
            throw error;
        }
    }, [client, schema]);
    const deleteSchema = useCallback(async (schemaId) => {
        try {
            setError(null);
            await client.deleteSchema(schemaId);
            if (schema && schema.id === schemaId) {
                setSchema(null);
            }
            setSchemas(prev => prev.filter(s => s.id !== schemaId));
        }
        catch (err) {
            const error = err instanceof Error ? err : new Error('Failed to delete schema');
            setError(error);
            throw error;
        }
    }, [client, schema]);
    const refresh = useCallback(async () => {
        try {
            setLoading(true);
            setError(null);
            if (schemaId) {
                const schemaData = await client.getSchema(schemaId);
                setSchema(schemaData);
            }
            else {
                const schemasData = await client.listSchemas({
                    projectId: projectId || client['config'].projectId,
                    isActive
                });
                setSchemas(schemasData);
            }
        }
        catch (err) {
            setError(err instanceof Error ? err : new Error('Failed to refresh schemas'));
        }
        finally {
            setLoading(false);
        }
    }, [client, schemaId, projectId, isActive]);
    return {
        schema,
        schemas,
        loading,
        error,
        createSchema,
        updateSchema,
        deleteSchema,
        refresh
    };
}

function useRealtime(client, options = {}) {
    const { autoConnect = true, reconnectAttempts = 5, reconnectDelay = 1000 } = options;
    const [isConnected, setIsConnected] = useState(false);
    const [isConnecting, setIsConnecting] = useState(false);
    const [error, setError] = useState(null);
    const [reconnectCount, setReconnectCount] = useState(0);
    const reconnectTimeoutRef = useRef(null);
    // Auto-connect on mount
    useEffect(() => {
        if (autoConnect && client) {
            connect();
        }
        return () => {
            if (reconnectTimeoutRef.current) {
                clearTimeout(reconnectTimeoutRef.current);
            }
        };
    }, [autoConnect, client]);
    // Connection event handlers
    useEffect(() => {
        if (!client)
            return;
        const handleConnect = () => {
            setIsConnected(true);
            setIsConnecting(false);
            setError(null);
            setReconnectCount(0);
        };
        const handleDisconnect = () => {
            setIsConnected(false);
            setIsConnecting(false);
        };
        const handleConnectError = (err) => {
            setIsConnecting(false);
            setError(err);
            // Auto-reconnect logic
            if (reconnectCount < reconnectAttempts) {
                setReconnectCount(prev => prev + 1);
                reconnectTimeoutRef.current = setTimeout(() => {
                    connect();
                }, reconnectDelay);
            }
        };
        const handleReconnect = (attempt) => {
            setIsConnecting(true);
            setError(null);
        };
        const handleReconnectAttempt = (attempt) => {
            setIsConnecting(true);
        };
        const handleReconnectError = () => {
            setIsConnecting(false);
            setError(new Error('Failed to reconnect'));
        };
        // Set up event listeners
        client.on('connected', handleConnect);
        client.on('disconnected', handleDisconnect);
        client.on('connection_error', handleConnectError);
        client.on('reconnect', handleReconnect);
        client.on('reconnect_attempt', handleReconnectAttempt);
        client.on('reconnect_error', handleReconnectError);
        return () => {
            client.off('connected', handleConnect);
            client.off('disconnected', handleDisconnect);
            client.off('connection_error', handleConnectError);
            client.off('reconnect', handleReconnect);
            client.off('reconnect_attempt', handleReconnectAttempt);
            client.off('reconnect_error', handleReconnectError);
        };
    }, [client, reconnectCount, reconnectAttempts, reconnectDelay]);
    const connect = useCallback(() => {
        if (!client || isConnected || isConnecting)
            return;
        setIsConnecting(true);
        setError(null);
        client.connect();
    }, [client, isConnected, isConnecting]);
    const disconnect = useCallback(() => {
        if (!client)
            return;
        if (reconnectTimeoutRef.current) {
            clearTimeout(reconnectTimeoutRef.current);
        }
        setIsConnecting(false);
        setReconnectCount(0);
        client.disconnect();
    }, [client]);
    const subscribe = useCallback((schemaId, callback) => {
        if (!client)
            return;
        client.subscribe(schemaId, callback);
    }, [client]);
    const unsubscribe = useCallback((schemaId, callback) => {
        if (!client)
            return;
        client.unsubscribe(schemaId, callback);
    }, [client]);
    const sendMessage = useCallback((event, data) => {
        if (!client || !isConnected)
            return;
        // This would need to be implemented in the client if needed
        // For now, we'll just emit events through the client
        client.on(event, data);
    }, [client, isConnected]);
    return {
        isConnected,
        isConnecting,
        error,
        connect,
        disconnect,
        subscribe,
        unsubscribe,
        sendMessage
    };
}
// Hook for subscribing to specific content updates
function useContentSubscription(client, schemaId, options = {}) {
    const [messages, setMessages] = useState([]);
    const [lastMessage, setLastMessage] = useState(null);
    const { isConnected, subscribe, unsubscribe } = useRealtime(client);
    useEffect(() => {
        if (!isConnected || !schemaId)
            return;
        const handleMessage = (message) => {
            setMessages(prev => [...prev, message]);
            setLastMessage(message);
        };
        subscribe(schemaId, handleMessage);
        return () => {
            unsubscribe(schemaId, handleMessage);
        };
    }, [isConnected, schemaId, subscribe, unsubscribe]);
    const clearMessages = useCallback(() => {
        setMessages([]);
        setLastMessage(null);
    }, []);
    return {
        messages,
        lastMessage,
        isConnected,
        clearMessages
    };
}
// Hook for optimistic updates with real-time sync
function useOptimisticRealtime(client, schemaId, initialData) {
    const [optimisticData, setOptimisticData] = useState(initialData);
    const [serverData, setServerData] = useState(initialData);
    const { isConnected, subscribe, unsubscribe } = useRealtime(client);
    useEffect(() => {
        if (!isConnected || !schemaId)
            return;
        const handleUpdate = (message) => {
            if (message.type === 'content:updated' || message.type === 'content:created') {
                setServerData(message.data);
                // Only update optimistic data if it hasn't been modified locally
                if (JSON.stringify(optimisticData) === JSON.stringify(serverData)) {
                    setOptimisticData(message.data);
                }
            }
        };
        subscribe(schemaId, handleUpdate);
        return () => {
            unsubscribe(schemaId, handleUpdate);
        };
    }, [isConnected, schemaId, subscribe, unsubscribe, optimisticData, serverData]);
    const updateOptimistic = useCallback((updates) => {
        setOptimisticData(prev => ({ ...prev, ...updates }));
    }, []);
    const syncWithServer = useCallback(() => {
        setOptimisticData(serverData);
    }, [serverData]);
    return {
        optimisticData,
        serverData,
        isConnected,
        updateOptimistic,
        syncWithServer
    };
}

var jsxRuntime = {exports: {}};

var reactJsxRuntime_production_min = {};

/**
 * @license React
 * react-jsx-runtime.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

var hasRequiredReactJsxRuntime_production_min;

function requireReactJsxRuntime_production_min () {
	if (hasRequiredReactJsxRuntime_production_min) return reactJsxRuntime_production_min;
	hasRequiredReactJsxRuntime_production_min = 1;
var f=require$$0,k=Symbol.for("react.element"),l=Symbol.for("react.fragment"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:true,ref:true,__self:true,__source:true};
	function q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=""+g);void 0!==a.key&&(e=""+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a) void 0===d[b]&&(d[b]=a[b]);return {$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}reactJsxRuntime_production_min.Fragment=l;reactJsxRuntime_production_min.jsx=q;reactJsxRuntime_production_min.jsxs=q;
	return reactJsxRuntime_production_min;
}

var reactJsxRuntime_development = {};

/**
 * @license React
 * react-jsx-runtime.development.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

var hasRequiredReactJsxRuntime_development;

function requireReactJsxRuntime_development () {
	if (hasRequiredReactJsxRuntime_development) return reactJsxRuntime_development;
	hasRequiredReactJsxRuntime_development = 1;

	if (process.env.NODE_ENV !== "production") {
	  (function() {

	var React = require$$0;

	// ATTENTION
	// When adding new symbols to this file,
	// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
	// The Symbol used to tag the ReactElement-like types.
	var REACT_ELEMENT_TYPE = Symbol.for('react.element');
	var REACT_PORTAL_TYPE = Symbol.for('react.portal');
	var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
	var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
	var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
	var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
	var REACT_CONTEXT_TYPE = Symbol.for('react.context');
	var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
	var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
	var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
	var REACT_MEMO_TYPE = Symbol.for('react.memo');
	var REACT_LAZY_TYPE = Symbol.for('react.lazy');
	var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
	var MAYBE_ITERATOR_SYMBOL = Symbol.iterator;
	var FAUX_ITERATOR_SYMBOL = '@@iterator';
	function getIteratorFn(maybeIterable) {
	  if (maybeIterable === null || typeof maybeIterable !== 'object') {
	    return null;
	  }

	  var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];

	  if (typeof maybeIterator === 'function') {
	    return maybeIterator;
	  }

	  return null;
	}

	var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

	function error(format) {
	  {
	    {
	      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
	        args[_key2 - 1] = arguments[_key2];
	      }

	      printWarning('error', format, args);
	    }
	  }
	}

	function printWarning(level, format, args) {
	  // When changing this logic, you might want to also
	  // update consoleWithStackDev.www.js as well.
	  {
	    var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;
	    var stack = ReactDebugCurrentFrame.getStackAddendum();

	    if (stack !== '') {
	      format += '%s';
	      args = args.concat([stack]);
	    } // eslint-disable-next-line react-internal/safe-string-coercion


	    var argsWithFormat = args.map(function (item) {
	      return String(item);
	    }); // Careful: RN currently depends on this prefix

	    argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it
	    // breaks IE9: https://github.com/facebook/react/issues/13610
	    // eslint-disable-next-line react-internal/no-production-logging

	    Function.prototype.apply.call(console[level], console, argsWithFormat);
	  }
	}

	// -----------------------------------------------------------------------------

	var enableScopeAPI = false; // Experimental Create Event Handle API.
	var enableCacheElement = false;
	var enableTransitionTracing = false; // No known bugs, but needs performance testing

	var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
	// stuff. Intended to enable React core members to more easily debug scheduling
	// issues in DEV builds.

	var enableDebugTracing = false; // Track which Fiber(s) schedule render work.

	var REACT_MODULE_REFERENCE;

	{
	  REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');
	}

	function isValidElementType(type) {
	  if (typeof type === 'string' || typeof type === 'function') {
	    return true;
	  } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).


	  if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing  || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden  || type === REACT_OFFSCREEN_TYPE || enableScopeAPI  || enableCacheElement  || enableTransitionTracing ) {
	    return true;
	  }

	  if (typeof type === 'object' && type !== null) {
	    if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
	    // types supported by any Flight configuration anywhere since
	    // we don't know which Flight build this will end up being used
	    // with.
	    type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
	      return true;
	    }
	  }

	  return false;
	}

	function getWrappedName(outerType, innerType, wrapperName) {
	  var displayName = outerType.displayName;

	  if (displayName) {
	    return displayName;
	  }

	  var functionName = innerType.displayName || innerType.name || '';
	  return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName;
	} // Keep in sync with react-reconciler/getComponentNameFromFiber


	function getContextName(type) {
	  return type.displayName || 'Context';
	} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.


	function getComponentNameFromType(type) {
	  if (type == null) {
	    // Host root, text node or just invalid type.
	    return null;
	  }

	  {
	    if (typeof type.tag === 'number') {
	      error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');
	    }
	  }

	  if (typeof type === 'function') {
	    return type.displayName || type.name || null;
	  }

	  if (typeof type === 'string') {
	    return type;
	  }

	  switch (type) {
	    case REACT_FRAGMENT_TYPE:
	      return 'Fragment';

	    case REACT_PORTAL_TYPE:
	      return 'Portal';

	    case REACT_PROFILER_TYPE:
	      return 'Profiler';

	    case REACT_STRICT_MODE_TYPE:
	      return 'StrictMode';

	    case REACT_SUSPENSE_TYPE:
	      return 'Suspense';

	    case REACT_SUSPENSE_LIST_TYPE:
	      return 'SuspenseList';

	  }

	  if (typeof type === 'object') {
	    switch (type.$$typeof) {
	      case REACT_CONTEXT_TYPE:
	        var context = type;
	        return getContextName(context) + '.Consumer';

	      case REACT_PROVIDER_TYPE:
	        var provider = type;
	        return getContextName(provider._context) + '.Provider';

	      case REACT_FORWARD_REF_TYPE:
	        return getWrappedName(type, type.render, 'ForwardRef');

	      case REACT_MEMO_TYPE:
	        var outerName = type.displayName || null;

	        if (outerName !== null) {
	          return outerName;
	        }

	        return getComponentNameFromType(type.type) || 'Memo';

	      case REACT_LAZY_TYPE:
	        {
	          var lazyComponent = type;
	          var payload = lazyComponent._payload;
	          var init = lazyComponent._init;

	          try {
	            return getComponentNameFromType(init(payload));
	          } catch (x) {
	            return null;
	          }
	        }

	      // eslint-disable-next-line no-fallthrough
	    }
	  }

	  return null;
	}

	var assign = Object.assign;

	// Helpers to patch console.logs to avoid logging during side-effect free
	// replaying on render function. This currently only patches the object
	// lazily which won't cover if the log function was extracted eagerly.
	// We could also eagerly patch the method.
	var disabledDepth = 0;
	var prevLog;
	var prevInfo;
	var prevWarn;
	var prevError;
	var prevGroup;
	var prevGroupCollapsed;
	var prevGroupEnd;

	function disabledLog() {}

	disabledLog.__reactDisabledLog = true;
	function disableLogs() {
	  {
	    if (disabledDepth === 0) {
	      /* eslint-disable react-internal/no-production-logging */
	      prevLog = console.log;
	      prevInfo = console.info;
	      prevWarn = console.warn;
	      prevError = console.error;
	      prevGroup = console.group;
	      prevGroupCollapsed = console.groupCollapsed;
	      prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099

	      var props = {
	        configurable: true,
	        enumerable: true,
	        value: disabledLog,
	        writable: true
	      }; // $FlowFixMe Flow thinks console is immutable.

	      Object.defineProperties(console, {
	        info: props,
	        log: props,
	        warn: props,
	        error: props,
	        group: props,
	        groupCollapsed: props,
	        groupEnd: props
	      });
	      /* eslint-enable react-internal/no-production-logging */
	    }

	    disabledDepth++;
	  }
	}
	function reenableLogs() {
	  {
	    disabledDepth--;

	    if (disabledDepth === 0) {
	      /* eslint-disable react-internal/no-production-logging */
	      var props = {
	        configurable: true,
	        enumerable: true,
	        writable: true
	      }; // $FlowFixMe Flow thinks console is immutable.

	      Object.defineProperties(console, {
	        log: assign({}, props, {
	          value: prevLog
	        }),
	        info: assign({}, props, {
	          value: prevInfo
	        }),
	        warn: assign({}, props, {
	          value: prevWarn
	        }),
	        error: assign({}, props, {
	          value: prevError
	        }),
	        group: assign({}, props, {
	          value: prevGroup
	        }),
	        groupCollapsed: assign({}, props, {
	          value: prevGroupCollapsed
	        }),
	        groupEnd: assign({}, props, {
	          value: prevGroupEnd
	        })
	      });
	      /* eslint-enable react-internal/no-production-logging */
	    }

	    if (disabledDepth < 0) {
	      error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');
	    }
	  }
	}

	var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;
	var prefix;
	function describeBuiltInComponentFrame(name, source, ownerFn) {
	  {
	    if (prefix === undefined) {
	      // Extract the VM specific prefix used by each line.
	      try {
	        throw Error();
	      } catch (x) {
	        var match = x.stack.trim().match(/\n( *(at )?)/);
	        prefix = match && match[1] || '';
	      }
	    } // We use the prefix to ensure our stacks line up with native stack frames.


	    return '\n' + prefix + name;
	  }
	}
	var reentry = false;
	var componentFrameCache;

	{
	  var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;
	  componentFrameCache = new PossiblyWeakMap();
	}

	function describeNativeComponentFrame(fn, construct) {
	  // If something asked for a stack inside a fake render, it should get ignored.
	  if ( !fn || reentry) {
	    return '';
	  }

	  {
	    var frame = componentFrameCache.get(fn);

	    if (frame !== undefined) {
	      return frame;
	    }
	  }

	  var control;
	  reentry = true;
	  var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.

	  Error.prepareStackTrace = undefined;
	  var previousDispatcher;

	  {
	    previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function
	    // for warnings.

	    ReactCurrentDispatcher.current = null;
	    disableLogs();
	  }

	  try {
	    // This should throw.
	    if (construct) {
	      // Something should be setting the props in the constructor.
	      var Fake = function () {
	        throw Error();
	      }; // $FlowFixMe


	      Object.defineProperty(Fake.prototype, 'props', {
	        set: function () {
	          // We use a throwing setter instead of frozen or non-writable props
	          // because that won't throw in a non-strict mode function.
	          throw Error();
	        }
	      });

	      if (typeof Reflect === 'object' && Reflect.construct) {
	        // We construct a different control for this case to include any extra
	        // frames added by the construct call.
	        try {
	          Reflect.construct(Fake, []);
	        } catch (x) {
	          control = x;
	        }

	        Reflect.construct(fn, [], Fake);
	      } else {
	        try {
	          Fake.call();
	        } catch (x) {
	          control = x;
	        }

	        fn.call(Fake.prototype);
	      }
	    } else {
	      try {
	        throw Error();
	      } catch (x) {
	        control = x;
	      }

	      fn();
	    }
	  } catch (sample) {
	    // This is inlined manually because closure doesn't do it for us.
	    if (sample && control && typeof sample.stack === 'string') {
	      // This extracts the first frame from the sample that isn't also in the control.
	      // Skipping one frame that we assume is the frame that calls the two.
	      var sampleLines = sample.stack.split('\n');
	      var controlLines = control.stack.split('\n');
	      var s = sampleLines.length - 1;
	      var c = controlLines.length - 1;

	      while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {
	        // We expect at least one stack frame to be shared.
	        // Typically this will be the root most one. However, stack frames may be
	        // cut off due to maximum stack limits. In this case, one maybe cut off
	        // earlier than the other. We assume that the sample is longer or the same
	        // and there for cut off earlier. So we should find the root most frame in
	        // the sample somewhere in the control.
	        c--;
	      }

	      for (; s >= 1 && c >= 0; s--, c--) {
	        // Next we find the first one that isn't the same which should be the
	        // frame that called our sample function and the control.
	        if (sampleLines[s] !== controlLines[c]) {
	          // In V8, the first line is describing the message but other VMs don't.
	          // If we're about to return the first line, and the control is also on the same
	          // line, that's a pretty good indicator that our sample threw at same line as
	          // the control. I.e. before we entered the sample frame. So we ignore this result.
	          // This can happen if you passed a class to function component, or non-function.
	          if (s !== 1 || c !== 1) {
	            do {
	              s--;
	              c--; // We may still have similar intermediate frames from the construct call.
	              // The next one that isn't the same should be our match though.

	              if (c < 0 || sampleLines[s] !== controlLines[c]) {
	                // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier.
	                var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "<anonymous>"
	                // but we have a user-provided "displayName"
	                // splice it in to make the stack more readable.


	                if (fn.displayName && _frame.includes('<anonymous>')) {
	                  _frame = _frame.replace('<anonymous>', fn.displayName);
	                }

	                {
	                  if (typeof fn === 'function') {
	                    componentFrameCache.set(fn, _frame);
	                  }
	                } // Return the line we found.


	                return _frame;
	              }
	            } while (s >= 1 && c >= 0);
	          }

	          break;
	        }
	      }
	    }
	  } finally {
	    reentry = false;

	    {
	      ReactCurrentDispatcher.current = previousDispatcher;
	      reenableLogs();
	    }

	    Error.prepareStackTrace = previousPrepareStackTrace;
	  } // Fallback to just using the name if we couldn't make it throw.


	  var name = fn ? fn.displayName || fn.name : '';
	  var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';

	  {
	    if (typeof fn === 'function') {
	      componentFrameCache.set(fn, syntheticFrame);
	    }
	  }

	  return syntheticFrame;
	}
	function describeFunctionComponentFrame(fn, source, ownerFn) {
	  {
	    return describeNativeComponentFrame(fn, false);
	  }
	}

	function shouldConstruct(Component) {
	  var prototype = Component.prototype;
	  return !!(prototype && prototype.isReactComponent);
	}

	function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {

	  if (type == null) {
	    return '';
	  }

	  if (typeof type === 'function') {
	    {
	      return describeNativeComponentFrame(type, shouldConstruct(type));
	    }
	  }

	  if (typeof type === 'string') {
	    return describeBuiltInComponentFrame(type);
	  }

	  switch (type) {
	    case REACT_SUSPENSE_TYPE:
	      return describeBuiltInComponentFrame('Suspense');

	    case REACT_SUSPENSE_LIST_TYPE:
	      return describeBuiltInComponentFrame('SuspenseList');
	  }

	  if (typeof type === 'object') {
	    switch (type.$$typeof) {
	      case REACT_FORWARD_REF_TYPE:
	        return describeFunctionComponentFrame(type.render);

	      case REACT_MEMO_TYPE:
	        // Memo may contain any component type so we recursively resolve it.
	        return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);

	      case REACT_LAZY_TYPE:
	        {
	          var lazyComponent = type;
	          var payload = lazyComponent._payload;
	          var init = lazyComponent._init;

	          try {
	            // Lazy may contain any component type so we recursively resolve it.
	            return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);
	          } catch (x) {}
	        }
	    }
	  }

	  return '';
	}

	var hasOwnProperty = Object.prototype.hasOwnProperty;

	var loggedTypeFailures = {};
	var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;

	function setCurrentlyValidatingElement(element) {
	  {
	    if (element) {
	      var owner = element._owner;
	      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);
	      ReactDebugCurrentFrame.setExtraStackFrame(stack);
	    } else {
	      ReactDebugCurrentFrame.setExtraStackFrame(null);
	    }
	  }
	}

	function checkPropTypes(typeSpecs, values, location, componentName, element) {
	  {
	    // $FlowFixMe This is okay but Flow doesn't know it.
	    var has = Function.call.bind(hasOwnProperty);

	    for (var typeSpecName in typeSpecs) {
	      if (has(typeSpecs, typeSpecName)) {
	        var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to
	        // fail the render phase where it didn't fail before. So we log it.
	        // After these have been cleaned up, we'll let them throw.

	        try {
	          // This is intentionally an invariant that gets caught. It's the same
	          // behavior as without this statement except with a better message.
	          if (typeof typeSpecs[typeSpecName] !== 'function') {
	            // eslint-disable-next-line react-internal/prod-error-codes
	            var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');
	            err.name = 'Invariant Violation';
	            throw err;
	          }

	          error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');
	        } catch (ex) {
	          error$1 = ex;
	        }

	        if (error$1 && !(error$1 instanceof Error)) {
	          setCurrentlyValidatingElement(element);

	          error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);

	          setCurrentlyValidatingElement(null);
	        }

	        if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {
	          // Only monitor this failure once because there tends to be a lot of the
	          // same error.
	          loggedTypeFailures[error$1.message] = true;
	          setCurrentlyValidatingElement(element);

	          error('Failed %s type: %s', location, error$1.message);

	          setCurrentlyValidatingElement(null);
	        }
	      }
	    }
	  }
	}

	var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare

	function isArray(a) {
	  return isArrayImpl(a);
	}

	/*
	 * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol
	 * and Temporal.* types. See https://github.com/facebook/react/pull/22064.
	 *
	 * The functions in this module will throw an easier-to-understand,
	 * easier-to-debug exception with a clear errors message message explaining the
	 * problem. (Instead of a confusing exception thrown inside the implementation
	 * of the `value` object).
	 */
	// $FlowFixMe only called in DEV, so void return is not possible.
	function typeName(value) {
	  {
	    // toStringTag is needed for namespaced types like Temporal.Instant
	    var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;
	    var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';
	    return type;
	  }
	} // $FlowFixMe only called in DEV, so void return is not possible.


	function willCoercionThrow(value) {
	  {
	    try {
	      testStringCoercion(value);
	      return false;
	    } catch (e) {
	      return true;
	    }
	  }
	}

	function testStringCoercion(value) {
	  // If you ended up here by following an exception call stack, here's what's
	  // happened: you supplied an object or symbol value to React (as a prop, key,
	  // DOM attribute, CSS property, string ref, etc.) and when React tried to
	  // coerce it to a string using `'' + value`, an exception was thrown.
	  //
	  // The most common types that will cause this exception are `Symbol` instances
	  // and Temporal objects like `Temporal.Instant`. But any object that has a
	  // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this
	  // exception. (Library authors do this to prevent users from using built-in
	  // numeric operators like `+` or comparison operators like `>=` because custom
	  // methods are needed to perform accurate arithmetic or comparison.)
	  //
	  // To fix the problem, coerce this object or symbol value to a string before
	  // passing it to React. The most reliable way is usually `String(value)`.
	  //
	  // To find which value is throwing, check the browser or debugger console.
	  // Before this exception was thrown, there should be `console.error` output
	  // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the
	  // problem and how that type was used: key, atrribute, input value prop, etc.
	  // In most cases, this console output also shows the component and its
	  // ancestor components where the exception happened.
	  //
	  // eslint-disable-next-line react-internal/safe-string-coercion
	  return '' + value;
	}
	function checkKeyStringCoercion(value) {
	  {
	    if (willCoercionThrow(value)) {
	      error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));

	      return testStringCoercion(value); // throw (to help callers find troubleshooting comments)
	    }
	  }
	}

	var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;
	var RESERVED_PROPS = {
	  key: true,
	  ref: true,
	  __self: true,
	  __source: true
	};
	var specialPropKeyWarningShown;
	var specialPropRefWarningShown;

	function hasValidRef(config) {
	  {
	    if (hasOwnProperty.call(config, 'ref')) {
	      var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;

	      if (getter && getter.isReactWarning) {
	        return false;
	      }
	    }
	  }

	  return config.ref !== undefined;
	}

	function hasValidKey(config) {
	  {
	    if (hasOwnProperty.call(config, 'key')) {
	      var getter = Object.getOwnPropertyDescriptor(config, 'key').get;

	      if (getter && getter.isReactWarning) {
	        return false;
	      }
	    }
	  }

	  return config.key !== undefined;
	}

	function warnIfStringRefCannotBeAutoConverted(config, self) {
	  {
	    if (typeof config.ref === 'string' && ReactCurrentOwner.current && self) ;
	  }
	}

	function defineKeyPropWarningGetter(props, displayName) {
	  {
	    var warnAboutAccessingKey = function () {
	      if (!specialPropKeyWarningShown) {
	        specialPropKeyWarningShown = true;

	        error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
	      }
	    };

	    warnAboutAccessingKey.isReactWarning = true;
	    Object.defineProperty(props, 'key', {
	      get: warnAboutAccessingKey,
	      configurable: true
	    });
	  }
	}

	function defineRefPropWarningGetter(props, displayName) {
	  {
	    var warnAboutAccessingRef = function () {
	      if (!specialPropRefWarningShown) {
	        specialPropRefWarningShown = true;

	        error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);
	      }
	    };

	    warnAboutAccessingRef.isReactWarning = true;
	    Object.defineProperty(props, 'ref', {
	      get: warnAboutAccessingRef,
	      configurable: true
	    });
	  }
	}
	/**
	 * Factory method to create a new React element. This no longer adheres to
	 * the class pattern, so do not use new to call it. Also, instanceof check
	 * will not work. Instead test $$typeof field against Symbol.for('react.element') to check
	 * if something is a React Element.
	 *
	 * @param {*} type
	 * @param {*} props
	 * @param {*} key
	 * @param {string|object} ref
	 * @param {*} owner
	 * @param {*} self A *temporary* helper to detect places where `this` is
	 * different from the `owner` when React.createElement is called, so that we
	 * can warn. We want to get rid of owner and replace string `ref`s with arrow
	 * functions, and as long as `this` and owner are the same, there will be no
	 * change in behavior.
	 * @param {*} source An annotation object (added by a transpiler or otherwise)
	 * indicating filename, line number, and/or other information.
	 * @internal
	 */


	var ReactElement = function (type, key, ref, self, source, owner, props) {
	  var element = {
	    // This tag allows us to uniquely identify this as a React Element
	    $$typeof: REACT_ELEMENT_TYPE,
	    // Built-in properties that belong on the element
	    type: type,
	    key: key,
	    ref: ref,
	    props: props,
	    // Record the component responsible for creating this element.
	    _owner: owner
	  };

	  {
	    // The validation flag is currently mutative. We put it on
	    // an external backing store so that we can freeze the whole object.
	    // This can be replaced with a WeakMap once they are implemented in
	    // commonly used development environments.
	    element._store = {}; // To make comparing ReactElements easier for testing purposes, we make
	    // the validation flag non-enumerable (where possible, which should
	    // include every environment we run tests in), so the test framework
	    // ignores it.

	    Object.defineProperty(element._store, 'validated', {
	      configurable: false,
	      enumerable: false,
	      writable: true,
	      value: false
	    }); // self and source are DEV only properties.

	    Object.defineProperty(element, '_self', {
	      configurable: false,
	      enumerable: false,
	      writable: false,
	      value: self
	    }); // Two elements created in two different places should be considered
	    // equal for testing purposes and therefore we hide it from enumeration.

	    Object.defineProperty(element, '_source', {
	      configurable: false,
	      enumerable: false,
	      writable: false,
	      value: source
	    });

	    if (Object.freeze) {
	      Object.freeze(element.props);
	      Object.freeze(element);
	    }
	  }

	  return element;
	};
	/**
	 * https://github.com/reactjs/rfcs/pull/107
	 * @param {*} type
	 * @param {object} props
	 * @param {string} key
	 */

	function jsxDEV(type, config, maybeKey, source, self) {
	  {
	    var propName; // Reserved names are extracted

	    var props = {};
	    var key = null;
	    var ref = null; // Currently, key can be spread in as a prop. This causes a potential
	    // issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
	    // or <div key="Hi" {...props} /> ). We want to deprecate key spread,
	    // but as an intermediary step, we will use jsxDEV for everything except
	    // <div {...props} key="Hi" />, because we aren't currently able to tell if
	    // key is explicitly declared to be undefined or not.

	    if (maybeKey !== undefined) {
	      {
	        checkKeyStringCoercion(maybeKey);
	      }

	      key = '' + maybeKey;
	    }

	    if (hasValidKey(config)) {
	      {
	        checkKeyStringCoercion(config.key);
	      }

	      key = '' + config.key;
	    }

	    if (hasValidRef(config)) {
	      ref = config.ref;
	      warnIfStringRefCannotBeAutoConverted(config, self);
	    } // Remaining properties are added to a new props object


	    for (propName in config) {
	      if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
	        props[propName] = config[propName];
	      }
	    } // Resolve default props


	    if (type && type.defaultProps) {
	      var defaultProps = type.defaultProps;

	      for (propName in defaultProps) {
	        if (props[propName] === undefined) {
	          props[propName] = defaultProps[propName];
	        }
	      }
	    }

	    if (key || ref) {
	      var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;

	      if (key) {
	        defineKeyPropWarningGetter(props, displayName);
	      }

	      if (ref) {
	        defineRefPropWarningGetter(props, displayName);
	      }
	    }

	    return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
	  }
	}

	var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;
	var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;

	function setCurrentlyValidatingElement$1(element) {
	  {
	    if (element) {
	      var owner = element._owner;
	      var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);
	      ReactDebugCurrentFrame$1.setExtraStackFrame(stack);
	    } else {
	      ReactDebugCurrentFrame$1.setExtraStackFrame(null);
	    }
	  }
	}

	var propTypesMisspellWarningShown;

	{
	  propTypesMisspellWarningShown = false;
	}
	/**
	 * Verifies the object is a ReactElement.
	 * See https://reactjs.org/docs/react-api.html#isvalidelement
	 * @param {?object} object
	 * @return {boolean} True if `object` is a ReactElement.
	 * @final
	 */


	function isValidElement(object) {
	  {
	    return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
	  }
	}

	function getDeclarationErrorAddendum() {
	  {
	    if (ReactCurrentOwner$1.current) {
	      var name = getComponentNameFromType(ReactCurrentOwner$1.current.type);

	      if (name) {
	        return '\n\nCheck the render method of `' + name + '`.';
	      }
	    }

	    return '';
	  }
	}

	function getSourceInfoErrorAddendum(source) {
	  {

	    return '';
	  }
	}
	/**
	 * Warn if there's no key explicitly set on dynamic arrays of children or
	 * object keys are not valid. This allows us to keep track of children between
	 * updates.
	 */


	var ownerHasKeyUseWarning = {};

	function getCurrentComponentErrorInfo(parentType) {
	  {
	    var info = getDeclarationErrorAddendum();

	    if (!info) {
	      var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;

	      if (parentName) {
	        info = "\n\nCheck the top-level render call using <" + parentName + ">.";
	      }
	    }

	    return info;
	  }
	}
	/**
	 * Warn if the element doesn't have an explicit key assigned to it.
	 * This element is in an array. The array could grow and shrink or be
	 * reordered. All children that haven't already been validated are required to
	 * have a "key" property assigned to it. Error statuses are cached so a warning
	 * will only be shown once.
	 *
	 * @internal
	 * @param {ReactElement} element Element that requires a key.
	 * @param {*} parentType element's parent's type.
	 */


	function validateExplicitKey(element, parentType) {
	  {
	    if (!element._store || element._store.validated || element.key != null) {
	      return;
	    }

	    element._store.validated = true;
	    var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);

	    if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {
	      return;
	    }

	    ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a
	    // property, it may be the creator of the child that's responsible for
	    // assigning it a key.

	    var childOwner = '';

	    if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {
	      // Give the component that originally created this child.
	      childOwner = " It was passed a child from " + getComponentNameFromType(element._owner.type) + ".";
	    }

	    setCurrentlyValidatingElement$1(element);

	    error('Each child in a list should have a unique "key" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);

	    setCurrentlyValidatingElement$1(null);
	  }
	}
	/**
	 * Ensure that every element either is passed in a static location, in an
	 * array with an explicit keys property defined, or in an object literal
	 * with valid key property.
	 *
	 * @internal
	 * @param {ReactNode} node Statically passed child of any type.
	 * @param {*} parentType node's parent's type.
	 */


	function validateChildKeys(node, parentType) {
	  {
	    if (typeof node !== 'object') {
	      return;
	    }

	    if (isArray(node)) {
	      for (var i = 0; i < node.length; i++) {
	        var child = node[i];

	        if (isValidElement(child)) {
	          validateExplicitKey(child, parentType);
	        }
	      }
	    } else if (isValidElement(node)) {
	      // This element was passed in a valid location.
	      if (node._store) {
	        node._store.validated = true;
	      }
	    } else if (node) {
	      var iteratorFn = getIteratorFn(node);

	      if (typeof iteratorFn === 'function') {
	        // Entry iterators used to provide implicit keys,
	        // but now we print a separate warning for them later.
	        if (iteratorFn !== node.entries) {
	          var iterator = iteratorFn.call(node);
	          var step;

	          while (!(step = iterator.next()).done) {
	            if (isValidElement(step.value)) {
	              validateExplicitKey(step.value, parentType);
	            }
	          }
	        }
	      }
	    }
	  }
	}
	/**
	 * Given an element, validate that its props follow the propTypes definition,
	 * provided by the type.
	 *
	 * @param {ReactElement} element
	 */


	function validatePropTypes(element) {
	  {
	    var type = element.type;

	    if (type === null || type === undefined || typeof type === 'string') {
	      return;
	    }

	    var propTypes;

	    if (typeof type === 'function') {
	      propTypes = type.propTypes;
	    } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.
	    // Inner props are checked in the reconciler.
	    type.$$typeof === REACT_MEMO_TYPE)) {
	      propTypes = type.propTypes;
	    } else {
	      return;
	    }

	    if (propTypes) {
	      // Intentionally inside to avoid triggering lazy initializers:
	      var name = getComponentNameFromType(type);
	      checkPropTypes(propTypes, element.props, 'prop', name, element);
	    } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {
	      propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:

	      var _name = getComponentNameFromType(type);

	      error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');
	    }

	    if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {
	      error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');
	    }
	  }
	}
	/**
	 * Given a fragment, validate that it can only be provided with fragment props
	 * @param {ReactElement} fragment
	 */


	function validateFragmentProps(fragment) {
	  {
	    var keys = Object.keys(fragment.props);

	    for (var i = 0; i < keys.length; i++) {
	      var key = keys[i];

	      if (key !== 'children' && key !== 'key') {
	        setCurrentlyValidatingElement$1(fragment);

	        error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);

	        setCurrentlyValidatingElement$1(null);
	        break;
	      }
	    }

	    if (fragment.ref !== null) {
	      setCurrentlyValidatingElement$1(fragment);

	      error('Invalid attribute `ref` supplied to `React.Fragment`.');

	      setCurrentlyValidatingElement$1(null);
	    }
	  }
	}

	var didWarnAboutKeySpread = {};
	function jsxWithValidation(type, props, key, isStaticChildren, source, self) {
	  {
	    var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to
	    // succeed and there will likely be errors in render.

	    if (!validType) {
	      var info = '';

	      if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {
	        info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports.";
	      }

	      var sourceInfo = getSourceInfoErrorAddendum();

	      if (sourceInfo) {
	        info += sourceInfo;
	      } else {
	        info += getDeclarationErrorAddendum();
	      }

	      var typeString;

	      if (type === null) {
	        typeString = 'null';
	      } else if (isArray(type)) {
	        typeString = 'array';
	      } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
	        typeString = "<" + (getComponentNameFromType(type.type) || 'Unknown') + " />";
	        info = ' Did you accidentally export a JSX literal instead of a component?';
	      } else {
	        typeString = typeof type;
	      }

	      error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);
	    }

	    var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.
	    // TODO: Drop this when these are no longer allowed as the type argument.

	    if (element == null) {
	      return element;
	    } // Skip key warning if the type isn't valid since our key validation logic
	    // doesn't expect a non-string/function type and can throw confusing errors.
	    // We don't want exception behavior to differ between dev and prod.
	    // (Rendering will throw with a helpful message and as soon as the type is
	    // fixed, the key warnings will appear.)


	    if (validType) {
	      var children = props.children;

	      if (children !== undefined) {
	        if (isStaticChildren) {
	          if (isArray(children)) {
	            for (var i = 0; i < children.length; i++) {
	              validateChildKeys(children[i], type);
	            }

	            if (Object.freeze) {
	              Object.freeze(children);
	            }
	          } else {
	            error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');
	          }
	        } else {
	          validateChildKeys(children, type);
	        }
	      }
	    }

	    {
	      if (hasOwnProperty.call(props, 'key')) {
	        var componentName = getComponentNameFromType(type);
	        var keys = Object.keys(props).filter(function (k) {
	          return k !== 'key';
	        });
	        var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}';

	        if (!didWarnAboutKeySpread[componentName + beforeExample]) {
	          var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';

	          error('A props object containing a "key" prop is being spread into JSX:\n' + '  let props = %s;\n' + '  <%s {...props} />\n' + 'React keys must be passed directly to JSX without using spread:\n' + '  let props = %s;\n' + '  <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName);

	          didWarnAboutKeySpread[componentName + beforeExample] = true;
	        }
	      }
	    }

	    if (type === REACT_FRAGMENT_TYPE) {
	      validateFragmentProps(element);
	    } else {
	      validatePropTypes(element);
	    }

	    return element;
	  }
	} // These two functions exist to still get child warnings in dev
	// even with the prod transform. This means that jsxDEV is purely
	// opt-in behavior for better messages but that we won't stop
	// giving you warnings if you use production apis.

	function jsxWithValidationStatic(type, props, key) {
	  {
	    return jsxWithValidation(type, props, key, true);
	  }
	}
	function jsxWithValidationDynamic(type, props, key) {
	  {
	    return jsxWithValidation(type, props, key, false);
	  }
	}

	var jsx =  jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.
	// for now we can ship identical prod functions

	var jsxs =  jsxWithValidationStatic ;

	reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE;
	reactJsxRuntime_development.jsx = jsx;
	reactJsxRuntime_development.jsxs = jsxs;
	  })();
	}
	return reactJsxRuntime_development;
}

if (process.env.NODE_ENV === 'production') {
  jsxRuntime.exports = requireReactJsxRuntime_production_min();
} else {
  jsxRuntime.exports = requireReactJsxRuntime_development();
}

var jsxRuntimeExports = jsxRuntime.exports;

function ContentEditor({ client, schemaId, contentId, onSave, onPublish, onCancel, className = '' }) {
    const { schema } = useSchema(client, { schemaId });
    const { content, updateContent, createContent, publishContent, loading, error } = useContent(client, {
        schemaId,
        contentId
    });
    const [formData, setFormData] = useState({});
    const [validationErrors, setValidationErrors] = useState({});
    const [isSaving, setIsSaving] = useState(false);
    const [isPublishing, setIsPublishing] = useState(false);
    // Initialize form data when schema or content changes
    useEffect(() => {
        if (schema) {
            const initialData = {};
            schema.fields.forEach(field => {
                if (content?.data && content.data[field.name] !== undefined) {
                    initialData[field.name] = content.data[field.name];
                }
                else if (field.defaultValue !== undefined) {
                    initialData[field.name] = field.defaultValue;
                }
                else {
                    initialData[field.name] = getDefaultValueForType(field.type);
                }
            });
            setFormData(initialData);
            setValidationErrors({});
        }
    }, [schema, content]);
    const getDefaultValueForType = (type) => {
        switch (type) {
            case 'text':
            case 'textarea':
            case 'url':
            case 'color':
                return '';
            case 'number':
                return 0;
            case 'boolean':
                return false;
            case 'array':
                return [];
            case 'object':
                return {};
            case 'date':
            case 'datetime':
                return new Date().toISOString().split('T')[0];
            default:
                return null;
        }
    };
    const handleFieldChange = useCallback((fieldName, value) => {
        setFormData(prev => ({ ...prev, [fieldName]: value }));
        // Clear validation error for this field
        if (validationErrors[fieldName]) {
            setValidationErrors(prev => {
                const newErrors = { ...prev };
                delete newErrors[fieldName];
                return newErrors;
            });
        }
    }, [validationErrors]);
    const validateForm = useCallback(() => {
        if (!schema)
            return false;
        const errors = {};
        schema.fields.forEach(field => {
            const value = formData[field.name];
            const validation = validateField(field, value);
            if (!validation.isValid) {
                errors[field.name] = validation.errors[0]?.message || `${field.label} is invalid`;
            }
        });
        setValidationErrors(errors);
        return Object.keys(errors).length === 0;
    }, [schema, formData]);
    const handleSave = useCallback(async () => {
        if (!validateForm())
            return;
        setIsSaving(true);
        try {
            let savedContent;
            if (contentId) {
                savedContent = await updateContent(contentId, { data: formData });
            }
            else {
                savedContent = await createContent({
                    schemaId,
                    projectId: client['config'].projectId || 1,
                    data: formData
                });
            }
            onSave?.(savedContent);
        }
        catch (err) {
            console.error('Failed to save content:', err);
        }
        finally {
            setIsSaving(false);
        }
    }, [validateForm, contentId, updateContent, createContent, formData, onSave, client]);
    const handlePublish = useCallback(async () => {
        if (!contentId)
            return;
        setIsPublishing(true);
        try {
            const publishedContent = await publishContent(contentId);
            onPublish?.(publishedContent);
        }
        catch (err) {
            console.error('Failed to publish content:', err);
        }
        finally {
            setIsPublishing(false);
        }
    }, [contentId, publishContent, onPublish]);
    const renderField = useCallback((field) => {
        const value = formData[field.name] || '';
        const error = validationErrors[field.name];
        const commonProps = {
            id: field.name,
            name: field.name,
            value: formatFieldValue(value, field.type),
            onChange: (e) => {
                const newValue = parseFieldValue(e.target.value, field.type);
                handleFieldChange(field.name, newValue);
            },
            className: `w-full p-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 ${error ? 'border-red-500' : 'border-gray-300'}`,
            placeholder: field.placeholder,
            required: field.required
        };
        switch (field.type) {
            case 'text':
            case 'url':
            case 'color':
                return (jsxRuntimeExports.jsx("input", { ...commonProps, type: field.type === 'color' ? 'color' : 'text' }));
            case 'textarea':
                return (jsxRuntimeExports.jsx("textarea", { ...commonProps, rows: 4, value: typeof value === 'string' ? value : '' }));
            case 'number':
                return (jsxRuntimeExports.jsx("input", { ...commonProps, type: "number", value: typeof value === 'number' ? value : '', onChange: (e) => {
                        const numValue = e.target.value ? parseFloat(e.target.value) : 0;
                        handleFieldChange(field.name, numValue);
                    } }));
            case 'boolean':
                return (jsxRuntimeExports.jsxs("div", { className: "flex items-center", children: [jsxRuntimeExports.jsx("input", { type: "checkbox", id: field.name, checked: Boolean(value), onChange: (e) => handleFieldChange(field.name, e.target.checked), className: "w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500" }), jsxRuntimeExports.jsx("label", { htmlFor: field.name, className: "ml-2 text-sm text-gray-700", children: field.label })] }));
            case 'select':
                return (jsxRuntimeExports.jsxs("select", { ...commonProps, children: [jsxRuntimeExports.jsxs("option", { value: "", children: ["Select ", field.label] }), field.options?.map(option => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
            case 'date':
            case 'datetime':
                return (jsxRuntimeExports.jsx("input", { ...commonProps, type: field.type === 'datetime' ? 'datetime-local' : 'date', value: value instanceof Date ? value.toISOString().split('T')[0] : value }));
            case 'array':
                return (jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("input", { ...commonProps, type: "text", value: Array.isArray(value) ? value.join(', ') : '', onChange: (e) => {
                                const arrayValue = e.target.value ? e.target.value.split(',').map(v => v.trim()) : [];
                                handleFieldChange(field.name, arrayValue);
                            } }), jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500 mt-1", children: "Separate values with commas" })] }));
            case 'object':
                return (jsxRuntimeExports.jsx("textarea", { ...commonProps, rows: 4, value: typeof value === 'object' ? JSON.stringify(value, null, 2) : '', onChange: (e) => {
                        try {
                            const objValue = e.target.value ? JSON.parse(e.target.value) : {};
                            handleFieldChange(field.name, objValue);
                        }
                        catch {
                            // Invalid JSON, keep as string
                            handleFieldChange(field.name, e.target.value);
                        }
                    } }));
            default:
                return (jsxRuntimeExports.jsx("input", { ...commonProps, type: "text" }));
        }
    }, [formData, validationErrors, handleFieldChange]);
    if (loading) {
        return (jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-center p-8 ${className}`, children: [jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }), jsxRuntimeExports.jsx("span", { className: "ml-2", children: "Loading..." })] }));
    }
    if (error) {
        return (jsxRuntimeExports.jsx("div", { className: `p-4 bg-red-50 border border-red-200 rounded-lg ${className}`, children: jsxRuntimeExports.jsxs("p", { className: "text-red-600", children: ["Error: ", error.message] }) }));
    }
    if (!schema) {
        return (jsxRuntimeExports.jsx("div", { className: `p-4 bg-yellow-50 border border-yellow-200 rounded-lg ${className}`, children: jsxRuntimeExports.jsx("p", { className: "text-yellow-600", children: "Schema not found" }) }));
    }
    return (jsxRuntimeExports.jsxs("div", { className: `space-y-6 ${className}`, children: [jsxRuntimeExports.jsxs("div", { className: "border-b border-gray-200 pb-4", children: [jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold text-gray-900", children: contentId ? 'Edit Content' : 'Create Content' }), jsxRuntimeExports.jsx("p", { className: "text-gray-600 mt-1", children: schema.name }), schema.description && (jsxRuntimeExports.jsx("p", { className: "text-sm text-gray-500 mt-2", children: schema.description }))] }), jsxRuntimeExports.jsxs("form", { className: "space-y-6", onSubmit: (e) => { e.preventDefault(); handleSave(); }, children: [schema.fields
                        .sort((a, b) => a.order - b.order)
                        .map(field => (jsxRuntimeExports.jsxs("div", { className: "space-y-2", children: [jsxRuntimeExports.jsxs("label", { htmlFor: field.name, className: "block text-sm font-medium text-gray-700", children: [field.label, field.required && jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), renderField(field), validationErrors[field.name] && (jsxRuntimeExports.jsx("p", { className: "text-sm text-red-600", children: validationErrors[field.name] })), field.helpText && (jsxRuntimeExports.jsx("p", { className: "text-xs text-gray-500", children: field.helpText }))] }, field.name))), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end space-x-3 pt-6 border-t border-gray-200", children: [onCancel && (jsxRuntimeExports.jsx("button", { type: "button", onClick: onCancel, className: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500", children: "Cancel" })), jsxRuntimeExports.jsx("button", { type: "submit", disabled: isSaving, className: "px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 disabled:opacity-50", children: isSaving ? 'Saving...' : 'Save' }), contentId && content && !content.isPublished && onPublish && (jsxRuntimeExports.jsx("button", { type: "button", onClick: handlePublish, disabled: isPublishing, className: "px-4 py-2 text-sm font-medium text-white bg-green-600 border border-transparent rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 disabled:opacity-50", children: isPublishing ? 'Publishing...' : 'Publish' }))] })] })] }));
}

class ErrorBoundary extends Component {
    constructor(props) {
        super(props);
        this.state = { hasError: false };
    }
    static getDerivedStateFromError(error) {
        return { hasError: true, error };
    }
    componentDidCatch(error, errorInfo) {
        this.setState({ error, errorInfo });
        if (this.props.onError) {
            this.props.onError(error, errorInfo);
        }
        // Log error to console in development
        if (process.env.NODE_ENV === 'development') {
            console.error('ErrorBoundary caught an error:', error, errorInfo);
        }
    }
    render() {
        if (this.state.hasError) {
            if (typeof this.props.fallback === 'function') {
                return this.props.fallback(this.state.error, this.state.errorInfo);
            }
            if (this.props.fallback) {
                return this.props.fallback;
            }
            // Default fallback UI
            return (jsxRuntimeExports.jsxs("div", { style: {
                    padding: '20px',
                    border: '1px solid #ff6b6b',
                    borderRadius: '8px',
                    backgroundColor: '#fff5f5',
                    color: '#c53030'
                }, children: [jsxRuntimeExports.jsx("h3", { children: "Something went wrong" }), jsxRuntimeExports.jsx("p", { children: "An error occurred while rendering this component." }), process.env.NODE_ENV === 'development' && this.state.error && (jsxRuntimeExports.jsxs("details", { style: { marginTop: '10px' }, children: [jsxRuntimeExports.jsx("summary", { children: "Error Details" }), jsxRuntimeExports.jsx("pre", { style: {
                                    fontSize: '12px',
                                    overflow: 'auto',
                                    backgroundColor: '#f7fafc',
                                    padding: '10px',
                                    borderRadius: '4px',
                                    marginTop: '10px'
                                }, children: this.state.error.toString() })] }))] }));
        }
        return this.props.children;
    }
}

class PerformanceMonitor {
    constructor() {
        this.metrics = [];
        this.maxMetrics = 1000; // Keep last 1000 metrics
    }
    recordMetric(metric) {
        const fullMetric = {
            ...metric,
            timestamp: Date.now()
        };
        this.metrics.push(fullMetric);
        // Keep only the last maxMetrics
        if (this.metrics.length > this.maxMetrics) {
            this.metrics = this.metrics.slice(-this.maxMetrics);
        }
    }
    getStats(timeWindow) {
        const now = Date.now();
        const relevantMetrics = timeWindow
            ? this.metrics.filter(m => now - m.timestamp < timeWindow)
            : this.metrics;
        if (relevantMetrics.length === 0) {
            return {
                totalCalls: 0,
                averageDuration: 0,
                successRate: 0,
                slowestOperation: null,
                fastestOperation: null
            };
        }
        const successfulCalls = relevantMetrics.filter(m => m.success);
        const durations = relevantMetrics.map(m => m.duration);
        const slowest = relevantMetrics.reduce((max, current) => current.duration > max.duration ? current : max);
        const fastest = relevantMetrics.reduce((min, current) => current.duration < min.duration ? current : min);
        return {
            totalCalls: relevantMetrics.length,
            averageDuration: durations.reduce((sum, duration) => sum + duration, 0) / durations.length,
            successRate: successfulCalls.length / relevantMetrics.length,
            slowestOperation: slowest,
            fastestOperation: fastest
        };
    }
    getOperationStats(operation, timeWindow) {
        const now = Date.now();
        const operationMetrics = this.metrics.filter(m => m.operation === operation &&
            (!timeWindow || now - m.timestamp < timeWindow));
        if (operationMetrics.length === 0) {
            return {
                totalCalls: 0,
                averageDuration: 0,
                successRate: 0,
                slowestOperation: null,
                fastestOperation: null
            };
        }
        const successfulCalls = operationMetrics.filter(m => m.success);
        const durations = operationMetrics.map(m => m.duration);
        const slowest = operationMetrics.reduce((max, current) => current.duration > max.duration ? current : max);
        const fastest = operationMetrics.reduce((min, current) => current.duration < min.duration ? current : min);
        return {
            totalCalls: operationMetrics.length,
            averageDuration: durations.reduce((sum, duration) => sum + duration, 0) / durations.length,
            successRate: successfulCalls.length / operationMetrics.length,
            slowestOperation: slowest,
            fastestOperation: fastest
        };
    }
    clear() {
        this.metrics = [];
    }
    exportMetrics() {
        return [...this.metrics];
    }
}
// Global performance monitor instance
const performanceMonitor = new PerformanceMonitor();
// Utility function to measure async operations
async function measureAsync(operation, fn) {
    const startTime = Date.now();
    try {
        const result = await fn();
        performanceMonitor.recordMetric({
            operation,
            duration: Date.now() - startTime,
            success: true
        });
        return result;
    }
    catch (error) {
        performanceMonitor.recordMetric({
            operation,
            duration: Date.now() - startTime,
            success: false,
            error: error instanceof Error ? error.message : String(error)
        });
        throw error;
    }
}
// Utility function to measure sync operations
function measureSync(operation, fn) {
    const startTime = Date.now();
    try {
        const result = fn();
        performanceMonitor.recordMetric({
            operation,
            duration: Date.now() - startTime,
            success: true
        });
        return result;
    }
    catch (error) {
        performanceMonitor.recordMetric({
            operation,
            duration: Date.now() - startTime,
            success: false,
            error: error instanceof Error ? error.message : String(error)
        });
        throw error;
    }
}

export { API_ENDPOINTS, ContentCache, ContentEditor, DEFAULT_CONFIG, ERROR_CODES, ErrorBoundary, FIELD_TYPES, LRUCache, PerformanceMonitor, REALTIME_EVENTS, ResolvoCMSClient, SchemaCache, VALIDATION_TYPES, ValidationError, createZodSchema, ResolvoCMSClient as default, deserializeContent, formatFieldValue, generateFieldId, measureAsync, measureSync, parseFieldValue, performanceMonitor, sanitizeFieldName, serializeContent, useContent, useContentSubscription, useOptimisticContent, useOptimisticRealtime, useRealtime, useSchema, validateContent, validateField };
//# sourceMappingURL=index.esm.js.map