'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import * as Tabs from '@radix-ui/react-tabs';
import { Bot, Eye, EyeOff, Loader2, AlertTriangle, Download, CheckCircle2, ArrowUpCircle, ExternalLink, RefreshCw, GitPullRequest, Layers, Users as UsersIcon, KeyRound, } from 'lucide-react';
import { useState, useEffect, useCallback, useMemo } from 'react';
import { toast } from 'sonner';
import { useApiData } from '../lib/useApiData.js';
import { cmsApi } from '../lib/api.js';
import { RelationshipField } from '../fields/RelationshipField.js';
import { GeneralSettingsTab } from './settings/GeneralSettingsTab.js';
import { SeoSettingsTab } from './settings/SeoSettingsTab.js';
import { AISettingsTab } from './settings/AISettingsTab.js';
import { AppearanceTab } from './settings/AppearanceTab.js';
import { SecurityTab } from './settings/SecurityTab.js';
import { SettingsCard } from './settings/components.js';
import { Users as UsersView } from './Users.js';
import { ApiKeys as ApiKeysView } from './ApiKeys.js';
/**
 * Tabs that persist through the shared footer's `handleSave` (which writes
 * `defaultLayout` into the settings global). Every other tab owns its own
 * saving, so the footer must NOT render there — otherwise it shows a
 * "Settings saved successfully!" toast while persisting nothing relevant.
 * This is an allowlist on purpose: new tabs default to self-managed.
 */
const GLOBAL_SAVE_TABS = new Set(['layout']);
function readSettingsTabFromUrl() {
    if (typeof window === 'undefined')
        return null;
    return new URLSearchParams(window.location.search).get('tab');
}
export function Settings({ config, onNavigate, session, initialTab = 'general', } = {}) {
    const { data, loading, error, refetch } = useApiData('/globals/settings');
    const [activeTab, setActiveTab] = useState(() => readSettingsTabFromUrl() ?? initialTab);
    const [saving, setSaving] = useState(false);
    // Layout defaults
    const [defaultLayout, setDefaultLayout] = useState({});
    const layoutConfig = config?.layout;
    const layoutRegions = layoutConfig?.regions
        ? Object.entries(layoutConfig.regions).map(([name, region]) => ({
            name,
            collection: region.collection,
            label: region.label ?? name.charAt(0).toUpperCase() + name.slice(1),
        }))
        : [];
    const hasLayoutRegions = layoutRegions.length > 0;
    // Valid tab ids, with `layout` only available when the project configures
    // layout regions. Used to normalise deep links and keep the URL honest.
    const availableTabs = useMemo(() => [
        'general',
        'appearance',
        ...(hasLayoutRegions ? ['layout'] : []),
        'security',
        'users',
        'api-keys',
        'seo',
        'ai',
        'updates',
    ], [hasLayoutRegions]);
    const normalizeTab = useCallback((tab) => tab && availableTabs.includes(tab) ? tab : 'general', [availableTabs]);
    // Drive the active tab from the `?tab=` query param so tabs are deep-linkable
    // and survive browser back/forward (the legacy /users and /api-keys routes
    // land here via `initialTab`).
    useEffect(() => {
        function sync() {
            setActiveTab(normalizeTab(readSettingsTabFromUrl() ?? initialTab));
        }
        sync();
        window.addEventListener('popstate', sync);
        return () => window.removeEventListener('popstate', sync);
    }, [normalizeTab, initialTab]);
    const changeTab = useCallback((tab) => {
        const next = normalizeTab(tab);
        setActiveTab(next);
        onNavigate?.(`/settings?tab=${next}`);
    }, [normalizeTab, onNavigate]);
    useEffect(() => {
        if (data) {
            if (data.defaultLayout && typeof data.defaultLayout === 'object') {
                setDefaultLayout(data.defaultLayout);
            }
        }
    }, [data]);
    const handleSave = async () => {
        setSaving(true);
        const layoutPayload = Object.keys(defaultLayout).length > 0 ? { defaultLayout } : {};
        // Read-modify-write: the General tab owns site info / SEO defaults in the
        // same global blob, so merge against a fresh fetch instead of overwriting.
        const current = await cmsApi('/globals/settings');
        const res = await cmsApi('/globals/settings', {
            method: 'PUT',
            body: JSON.stringify({
                ...(current.data ?? {}),
                ...layoutPayload,
            }),
        });
        setSaving(false);
        if (res.error) {
            toast.error(res.error);
        }
        else {
            toast.success('Settings saved successfully!');
        }
    };
    const tabTriggerClass = 'text-muted-foreground hover:text-foreground data-[state=active]:border-brand data-[state=active]:text-brand px-4 py-2 text-base font-medium transition-colors data-[state=active]:border-b-2';
    if (loading) {
        return (_jsx("div", { className: "flex h-64 items-center justify-center p-3 pr-6 sm:p-4 sm:pr-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-blue-600" }) }));
    }
    return (_jsxs("div", { className: "p-3 pr-6 sm:p-4 sm:pr-8", children: [error && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive mb-4 flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 20, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: error }), _jsx("button", { onClick: refetch, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), _jsxs("div", { className: "mb-4", children: [_jsx("h1", { className: "text-foreground mb-1 text-2xl font-medium", children: "Settings" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "Manage your CMS configuration" })] }), _jsxs(Tabs.Root, { value: activeTab, onValueChange: changeTab, children: [_jsxs(Tabs.List, { className: "border-border mb-4 flex gap-1 overflow-x-auto border-b", children: [_jsx(Tabs.Trigger, { value: "general", className: tabTriggerClass, children: "General" }), _jsx(Tabs.Trigger, { value: "appearance", className: tabTriggerClass, children: "Appearance" }), hasLayoutRegions && (_jsx(Tabs.Trigger, { value: "layout", className: tabTriggerClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Layers, { className: "h-4 w-4" }), "Layout"] }) })), _jsx(Tabs.Trigger, { value: "security", className: tabTriggerClass, children: "Security" }), _jsx(Tabs.Trigger, { value: "users", className: tabTriggerClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(UsersIcon, { className: "h-4 w-4" }), "Users"] }) }), _jsx(Tabs.Trigger, { value: "api-keys", className: tabTriggerClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(KeyRound, { className: "h-4 w-4" }), "API Keys"] }) }), _jsx(Tabs.Trigger, { value: "seo", className: tabTriggerClass, children: "SEO" }), _jsx(Tabs.Trigger, { value: "ai", className: tabTriggerClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Bot, { className: "h-4 w-4" }), "AI"] }) }), _jsx(Tabs.Trigger, { value: "updates", className: tabTriggerClass, children: _jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx(Download, { className: "h-4 w-4" }), "Updates"] }) })] }), _jsx(Tabs.Content, { value: "general", children: _jsx(GeneralSettingsTab, { onNavigate: onNavigate, role: session?.user?.role }) }), _jsx(Tabs.Content, { value: "appearance", className: "space-y-4", children: _jsx(AppearanceTab, { role: session?.user?.role, config: config }) }), hasLayoutRegions && (_jsxs(Tabs.Content, { value: "layout", className: "space-y-4", children: [_jsx(SettingsCard, { title: "Default Layout Variants", description: "Select the default header, footer, and other layout variants used site-wide. Pages can override these individually or inherit from parent pages.", children: _jsx("div", { className: "space-y-4", children: layoutRegions.map((region) => (_jsx(RelationshipField, { label: `Default ${region.label}`, value: defaultLayout[region.name] ?? '', onChange: (val) => {
                                            setDefaultLayout((prev) => {
                                                const next = { ...prev };
                                                if (val && typeof val === 'string') {
                                                    next[region.name] = val;
                                                }
                                                else {
                                                    delete next[region.name];
                                                }
                                                return next;
                                            });
                                        }, relationTo: region.collection, helpText: `The ${region.label.toLowerCase()} variant used when no page in the ancestor chain specifies one` }, region.name))) }) }), _jsx(SettingsCard, { title: "How Layout Inheritance Works", children: _jsxs("ul", { className: "text-muted-foreground space-y-1.5 text-sm", children: [_jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "1" }), _jsx("span", { children: "Each page can assign specific layout variants (header, footer, etc.) from the document editor." })] }), _jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "2" }), _jsxs("span", { children: ["Child pages automatically inherit their parent's layout. For example,", ' ', _jsx("code", { className: "bg-muted rounded px-1 font-mono", children: "/hampton-roads/thank-you" }), ' ', "inherits from", ' ', _jsx("code", { className: "bg-muted rounded px-1 font-mono", children: "/hampton-roads" }), "."] })] }), _jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "3" }), _jsx("span", { children: "If no page in the ancestor chain sets a variant, the defaults configured above are used." })] })] }) })] })), _jsx(Tabs.Content, { value: "security", className: "space-y-4", children: _jsx(SecurityTab, { role: session?.user?.role, onNavigate: onNavigate }) }), _jsx(Tabs.Content, { value: "seo", className: "space-y-4", children: _jsx(SeoSettingsTab, { onNavigate: onNavigate, role: session?.user?.role }) }), _jsx(Tabs.Content, { value: "ai", className: "space-y-4", children: _jsx(AISettingsTab, { role: session?.user?.role }) }), _jsx(Tabs.Content, { value: "users", children: _jsx(UsersView, { onNavigate: onNavigate, embedded: true }) }), _jsx(Tabs.Content, { value: "api-keys", children: _jsx(ApiKeysView, { onNavigate: onNavigate, embedded: true }) }), _jsx(Tabs.Content, { value: "updates", className: "space-y-4", children: _jsx(UpdatesPanel, {}) })] }), GLOBAL_SAVE_TABS.has(activeTab) && (_jsx("div", { className: "mt-6 flex justify-end", children: _jsx("button", { type: "button", onClick: handleSave, disabled: saving, className: "rounded-lg bg-blue-600 px-6 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: saving ? 'Saving...' : 'Save Changes' }) }))] }));
}
function UpdatesPanel() {
    const [updateInfo, setUpdateInfo] = useState(null);
    const [checking, setChecking] = useState(false);
    const [checkError, setCheckError] = useState('');
    const [applying, setApplying] = useState(false);
    const [prResult, setPrResult] = useState(null);
    const [hasChecked, setHasChecked] = useState(false);
    // GitHub config
    const [ghToken, setGhToken] = useState('');
    const [ghRepo, setGhRepo] = useState('');
    const [showGhToken, setShowGhToken] = useState(false);
    const [savingConfig, setSavingConfig] = useState(false);
    const [configSaved, setConfigSaved] = useState(false);
    const checkForUpdates = async () => {
        setChecking(true);
        setCheckError('');
        setPrResult(null);
        try {
            const res = await cmsApi('/updates/check');
            if (res.error) {
                setCheckError(res.error);
            }
            else if (res.data) {
                setUpdateInfo(res.data);
                if (res.data.githubRepo)
                    setGhRepo(res.data.githubRepo);
            }
        }
        catch {
            setCheckError('Unable to check for updates. Please try again.');
        }
        finally {
            setChecking(false);
            setHasChecked(true);
        }
    };
    const saveGitHubConfig = async () => {
        setSavingConfig(true);
        setConfigSaved(false);
        try {
            const res = await cmsApi('/updates/config', {
                method: 'PUT',
                body: JSON.stringify({
                    ...(ghToken ? { githubToken: ghToken } : {}),
                    ...(ghRepo ? { githubRepo: ghRepo } : {}),
                }),
            });
            if (res.error) {
                toast.error(res.error);
            }
            else {
                toast.success('GitHub configuration saved and encrypted.');
                setConfigSaved(true);
                setGhToken('');
                if (updateInfo) {
                    setUpdateInfo({ ...updateInfo, hasGithubToken: true, githubRepo: ghRepo });
                }
            }
        }
        catch {
            toast.error('Failed to save configuration.');
        }
        finally {
            setSavingConfig(false);
        }
    };
    const applyUpdate = async () => {
        if (!updateInfo?.latest)
            return;
        setApplying(true);
        try {
            const res = await cmsApi('/updates/apply', {
                method: 'POST',
                body: JSON.stringify({ targetVersion: updateInfo.latest }),
            });
            if (res.error) {
                toast.error(res.error);
            }
            else if (res.data) {
                setPrResult(res.data);
                toast.success('Update PR created successfully!');
            }
        }
        catch {
            toast.error('Failed to create update PR. Check your GitHub configuration.');
        }
        finally {
            setApplying(false);
        }
    };
    useEffect(() => {
        checkForUpdates();
    }, []);
    // Semantic severity tokens so update banners match the rest of the admin in
    // both light and dark mode (no raw palette colors). Concrete keys (not a
    // string-index Record) keep the lookup non-nullable.
    const severityColors = {
        patch: { banner: 'border-brand/30 bg-brand/10', text: 'text-brand', label: 'Patch' },
        minor: { banner: 'border-warning/30 bg-warning/10', text: 'text-warning', label: 'Minor' },
        major: {
            banner: 'border-destructive/30 bg-destructive/10',
            text: 'text-destructive',
            label: 'Major',
        },
    };
    const sev = severityColors[updateInfo?.severity ?? 'patch'];
    const ghInputClass = 'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none';
    return (_jsxs(_Fragment, { children: [_jsx(SettingsCard, { title: "Actuate CMS", description: "Keep your CMS up to date with the latest features and security patches.", actions: _jsxs("button", { type: "button", onClick: checkForUpdates, disabled: checking, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50", children: [_jsx(RefreshCw, { size: 16, className: checking ? 'animate-spin' : '', "aria-hidden": "true" }), checking ? 'Checking…' : 'Check for Updates'] }), children: _jsxs("p", { className: "text-muted-foreground text-sm", children: ["Current version:", ' ', _jsx("span", { className: "text-foreground font-mono font-medium", children: updateInfo?.current ?? '…' })] }) }), checkError && (_jsxs("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm", children: [_jsx(AlertTriangle, { size: 20, className: "shrink-0", "aria-hidden": "true" }), _jsx("span", { className: "flex-1", children: checkError }), _jsx("button", { onClick: checkForUpdates, className: "border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80", children: "Retry" })] })), hasChecked && updateInfo && !updateInfo.updateAvailable && !checkError && (_jsxs("div", { className: "border-success/30 bg-success/10 text-success flex items-center gap-3 rounded-lg border p-4", children: [_jsx(CheckCircle2, { size: 24, className: "shrink-0", "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("h3", { className: "text-foreground font-medium", children: "You're up to date!" }), _jsxs("p", { className: "text-muted-foreground mt-0.5 text-sm", children: ["Actuate CMS ", _jsx("span", { className: "font-mono", children: updateInfo.current }), " is the latest version."] })] })] })), updateInfo?.updateAvailable && (_jsxs(_Fragment, { children: [_jsxs("div", { className: `rounded-lg border p-4 ${sev.banner}`, children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx(ArrowUpCircle, { size: 24, className: `mt-0.5 shrink-0 ${sev.text}`, "aria-hidden": "true" }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h3", { className: `font-medium ${sev.text}`, children: "Update Available" }), _jsx("span", { className: `inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium ${sev.banner} ${sev.text}`, children: sev.label })] }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: [_jsx("span", { className: "font-mono", children: updateInfo.current }), " \u2192", ' ', _jsx("span", { className: "text-foreground font-mono font-medium", children: updateInfo.latest }), updateInfo.releaseDate && (_jsxs("span", { className: "ml-2 text-xs opacity-70", children: ["Released ", updateInfo.releaseDate] }))] })] })] }), _jsxs("div", { className: "mt-4 flex items-center gap-3", children: [_jsx("button", { type: "button", onClick: applyUpdate, disabled: applying, className: "bg-brand text-brand-foreground inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:opacity-50", children: applying ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "animate-spin", "aria-hidden": "true" }), "Creating PR\u2026"] })) : (_jsxs(_Fragment, { children: [_jsx(GitPullRequest, { size: 16, "aria-hidden": "true" }), "Create Update PR"] })) }), _jsx("span", { className: "text-muted-foreground text-xs", children: "Opens a pull request on your repository" })] }), updateInfo.updateCommand && (_jsxs("div", { className: "border-border bg-card mt-3 rounded-md border p-3", children: [_jsx("p", { className: "text-muted-foreground mb-1 text-xs", children: "Or update manually:" }), _jsx("code", { className: "bg-muted text-foreground block rounded px-2 py-1.5 font-mono text-xs select-all", children: updateInfo.updateCommand })] }))] }), updateInfo.changelog && updateInfo.changelog.length > 0 && (_jsx(SettingsCard, { title: "Changelog", children: _jsx("div", { className: "max-h-64 space-y-2 overflow-y-auto", children: updateInfo.changelog.map((entry) => (_jsxs("div", { className: "flex items-baseline gap-3 text-sm", children: [_jsx("span", { className: "text-muted-foreground w-14 shrink-0 font-mono text-xs", children: entry.version }), _jsx("span", { className: "text-muted-foreground w-20 shrink-0 text-xs", children: entry.date }), _jsx("span", { className: "text-foreground", children: entry.summary })] }, entry.version))) }) }))] })), prResult && (_jsx("div", { className: "border-success/30 bg-success/10 rounded-lg border p-4", children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(GitPullRequest, { size: 20, className: "text-success mt-0.5 shrink-0", "aria-hidden": "true" }), _jsxs("div", { children: [_jsx("h3", { className: "text-foreground font-medium", children: "Pull Request Created" }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: ["PR #", prResult.prNumber, " has been created on your repository. Review and merge it to apply the update, then run", ' ', _jsx("code", { className: "bg-muted rounded px-1 font-mono text-xs", children: "npx prisma migrate deploy" }), "."] }), _jsxs("a", { href: prResult.prUrl, target: "_blank", rel: "noopener noreferrer", className: "text-brand mt-2 inline-flex items-center gap-1.5 text-sm font-medium hover:underline", children: [_jsx(ExternalLink, { size: 16, "aria-hidden": "true" }), "View Pull Request"] })] })] }) })), _jsx(SettingsCard, { title: "GitHub Integration", description: "Connect your repository to enable one-click update PRs. Credentials are encrypted at rest (AES-256-GCM).", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: "updates-gh-repo", className: "text-foreground mb-1 block text-sm font-medium", children: "Repository" }), _jsx("input", { id: "updates-gh-repo", type: "text", value: ghRepo, onChange: (e) => setGhRepo(e.target.value), placeholder: "owner/repo", className: ghInputClass }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: ["e.g.", ' ', _jsx("code", { className: "bg-muted rounded px-1 font-mono", children: "actuate-media/my-client-site" })] })] }), _jsxs("div", { children: [_jsxs("label", { htmlFor: "updates-gh-token", className: "text-foreground mb-1 block text-sm font-medium", children: ["GitHub Token", updateInfo?.hasGithubToken && !ghToken && (_jsx("span", { className: "text-success ml-2 text-xs font-normal", children: "Saved" }))] }), _jsxs("div", { className: "relative", children: [_jsx("input", { id: "updates-gh-token", type: showGhToken ? 'text' : 'password', value: ghToken, onChange: (e) => setGhToken(e.target.value), placeholder: updateInfo?.hasGithubToken ? '••••••••••••••••' : 'ghp_... or github_pat_...', className: `${ghInputClass} pr-10` }), _jsx("button", { type: "button", onClick: () => setShowGhToken(!showGhToken), "aria-label": showGhToken ? 'Hide token' : 'Show token', className: "text-muted-foreground hover:text-foreground absolute top-1/2 right-2 -translate-y-1/2 p-1", children: showGhToken ? (_jsx(EyeOff, { size: 16, "aria-hidden": "true" })) : (_jsx(Eye, { size: 16, "aria-hidden": "true" })) })] }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: ["Needs ", _jsx("code", { className: "bg-muted rounded px-1 font-mono", children: "repo" }), " scope. Create at", ' ', _jsx("a", { href: "https://github.com/settings/tokens", target: "_blank", rel: "noopener noreferrer", className: "text-brand hover:underline", children: "github.com/settings/tokens" })] })] }), _jsx("button", { type: "button", onClick: saveGitHubConfig, disabled: savingConfig || (!ghToken && !ghRepo), className: "bg-brand text-brand-foreground inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:opacity-50", children: savingConfig ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "animate-spin", "aria-hidden": "true" }), "Encrypting & Saving\u2026"] })) : ('Save Configuration') })] }) }), _jsx(SettingsCard, { title: "How Updates Work", children: _jsxs("ul", { className: "text-muted-foreground space-y-1.5 text-sm", children: [_jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "1" }), _jsx("span", { children: "Click \"Check for Updates\" to see if a new version is available on npm." })] }), _jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "2" }), _jsx("span", { children: "Add your GitHub token and repository above. They're encrypted at rest \u2014 never stored in plaintext." })] }), _jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "3" }), _jsx("span", { children: "Click \"Create Update PR\" to open a pull request that bumps your CMS packages automatically." })] }), _jsxs("li", { className: "flex items-start gap-2", children: [_jsx("span", { className: "bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium", children: "4" }), _jsxs("span", { children: ["Review and merge the PR, then deploy. Database migrations run automatically via", ' ', _jsx("code", { className: "bg-muted rounded px-1 font-mono", children: "prisma migrate deploy" }), "."] })] })] }) })] }));
}
//# sourceMappingURL=Settings.js.map