UNPKG

ailock

Version:

AI-Proof File Guard - Protect sensitive files from accidental AI modifications

185 lines 10.7 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useEffect } from 'react'; import { Box, Text } from 'ink'; import SelectInput from 'ink-select-input'; import TextInput from 'ink-text-input'; import { writeFile, readFile } from 'fs/promises'; import { existsSync } from 'fs'; const PROJECT_TEMPLATES = [ { name: 'node', label: '📦 Node.js Project', description: 'Express, Nest.js, or other Node.js applications', patterns: [ '.env', '.env.*', '!.env.example', 'config/*.json', 'config/*.yaml', '**/*.key', '**/*.pem', '**/secrets.json' ] }, { name: 'docker', label: '🐳 Docker Project', description: 'Projects with Docker containers and orchestration', patterns: [ '.env', '.env.*', '!.env.example', 'docker-compose.yml', 'docker-compose.*.yml', 'Dockerfile.prod', 'k8s/**/*.yaml', 'config/*.yaml' ] }, { name: 'web', label: '🌐 Web Application', description: 'React, Vue, Angular, or other web applications', patterns: [ '.env', '.env.*', '!.env.example', '**/*.key', 'public/config.json', 'src/config/*.json', 'firebase.json', 'vercel.json' ] }, { name: 'python', label: '🐍 Python Project', description: 'Django, Flask, FastAPI, or other Python applications', patterns: [ '.env', '*.env', 'settings/*.py', 'config/*.yaml', 'secrets.json', '**/*.key', '**/*.pem' ] }, { name: 'custom', label: '⚙️ Custom Configuration', description: 'Define your own protection patterns', patterns: [] } ]; export const InitWizard = ({ onComplete, onCancel }) => { const [step, setStep] = useState('welcome'); const [selectedTemplate, setSelectedTemplate] = useState(null); const [customPatterns, setCustomPatterns] = useState([]); const [currentPattern, setCurrentPattern] = useState(''); const [editingCustom, setEditingCustom] = useState(false); const [existingConfig, setExistingConfig] = useState(null); useEffect(() => { // Check if .ailock already exists const ailockPath = '.ailock'; if (existsSync(ailockPath)) { readFile(ailockPath, 'utf-8').then(content => { setExistingConfig(content); }).catch(() => { setExistingConfig(null); }); } }, []); const handleWelcomeNext = () => { setStep('template'); }; const handleTemplateSelect = (template) => { setSelectedTemplate(template); if (template.name === 'custom') { setStep('custom-patterns'); } else { setStep('review'); } }; const handleAddCustomPattern = () => { if (currentPattern.trim()) { setCustomPatterns([...customPatterns, currentPattern.trim()]); setCurrentPattern(''); } }; const handleFinishCustom = () => { if (selectedTemplate) { selectedTemplate.patterns = customPatterns; } setStep('review'); }; const handleConfirmSetup = async () => { if (!selectedTemplate) return; try { // Generate .ailock content let content = `# AI-Proof File Guard Configuration\n`; content += `# Generated on ${new Date().toISOString()}\n`; content += `# Template: ${selectedTemplate.label}\n#\n`; content += `# This file uses gitignore-style syntax:\n`; content += `# - One pattern per line\n`; content += `# - # for comments\n`; content += `# - Supports glob patterns (**/*.ext, *.json, etc.)\n`; content += `# - ! for negation\n\n`; const patterns = selectedTemplate.patterns.length > 0 ? selectedTemplate.patterns : customPatterns; for (const pattern of patterns) { if (pattern.startsWith('!')) { content += `${pattern} # Negation pattern\n`; } else if (pattern.includes('*')) { content += `${pattern} # Glob pattern\n`; } else { content += `${pattern}\n`; } } // Write .ailock file await writeFile('.ailock', content); setStep('complete'); // Auto-complete after 2 seconds setTimeout(() => { onComplete(); }, 2000); } catch (error) { console.error('Failed to create .ailock file:', error); } }; if (step === 'welcome') { return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "blue", children: "\uD83D\uDE80 Welcome to AI-Proof File Guard Setup" }), _jsx(Text, {}), _jsx(Text, { children: "This wizard will help you set up file protection for your project." }), _jsx(Text, {}), existingConfig && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "yellow", children: "\u26A0\uFE0F .ailock file already exists" }), _jsx(Text, { color: "gray", children: "This wizard will overwrite your existing configuration." }), _jsx(Text, {})] })), _jsx(Text, { bold: true, children: "What ailock does:" }), _jsx(Text, { children: "\u2022 \uD83D\uDD12 Protects sensitive files from accidental AI modifications" }), _jsx(Text, { children: "\u2022 \uD83D\uDCD6 Keeps files readable for AI analysis and context" }), _jsx(Text, { children: "\u2022 \uD83D\uDEE1\uFE0F Provides multi-layer protection (OS + Git hooks)" }), _jsx(Text, {}), _jsx(Box, { children: _jsx(Text, { color: "green", children: "Press Enter to continue, or Ctrl+C to cancel" }) }), _jsx(TextInput, { value: "", onChange: () => { }, onSubmit: handleWelcomeNext, placeholder: "" })] })); } if (step === 'template') { const items = PROJECT_TEMPLATES.map(template => ({ label: `${template.label} - ${template.description}`, value: template })); return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "blue", children: "\uD83D\uDCCB Choose Project Template" }), _jsx(Text, {}), _jsx(Text, { children: "Select the template that best matches your project:" }), _jsx(Text, {}), _jsx(SelectInput, { items: items, onSelect: (item) => handleTemplateSelect(item.value) }), _jsx(Text, {}), _jsx(Text, { color: "gray", children: "Use arrow keys to navigate, Enter to select" })] })); } if (step === 'custom-patterns') { return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "blue", children: "\u2699\uFE0F Custom Protection Patterns" }), _jsx(Text, {}), _jsx(Text, { children: "Enter file patterns to protect (gitignore-style syntax):" }), _jsx(Text, { color: "gray", children: "Examples: .env, **/*.key, config/*.json, !*.example" }), _jsx(Text, {}), customPatterns.length > 0 && (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, children: "Current patterns:" }), customPatterns.map((pattern, index) => (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: "green", children: ["\u2713 ", pattern] }) }, index))), _jsx(Text, {})] })), !editingCustom ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: "Add pattern (Enter to add, 'done' to finish):" }), _jsx(TextInput, { value: currentPattern, onChange: setCurrentPattern, onSubmit: (value) => { if (value.toLowerCase() === 'done') { handleFinishCustom(); } else { handleAddCustomPattern(); } }, placeholder: ".env, **/*.key, etc." })] })) : null, _jsx(Text, {}), _jsx(Text, { color: "gray", children: "Type 'done' and press Enter when finished" })] })); } if (step === 'review') { const patterns = selectedTemplate?.patterns || customPatterns; return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "blue", children: "\uD83D\uDCDD Review Configuration" }), _jsx(Text, {}), _jsx(Text, { bold: true, children: "Template: " }), _jsx(Text, { color: "green", children: selectedTemplate?.label }), _jsx(Text, { color: "gray", children: selectedTemplate?.description }), _jsx(Text, {}), _jsx(Text, { bold: true, children: "Protection patterns:" }), patterns.length > 0 ? (patterns.map((pattern, index) => (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: pattern.startsWith('!') ? 'yellow' : 'blue', children: [pattern.startsWith('!') ? '🚫' : '🔒', " ", pattern] }) }, index)))) : (_jsx(Text, { color: "gray", children: "No patterns defined" })), _jsx(Text, {}), _jsx(Text, { children: "This will create a .ailock file in your project root." }), _jsx(Text, {}), _jsx(Box, { children: _jsx(Text, { color: "green", children: "Press Enter to create, or Ctrl+C to cancel" }) }), _jsx(TextInput, { value: "", onChange: () => { }, onSubmit: handleConfirmSetup, placeholder: "" })] })); } if (step === 'complete') { return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(Text, { bold: true, color: "green", children: "\u2705 Setup Complete!" }), _jsx(Text, {}), _jsx(Text, { children: "\uD83C\uDF89 Your .ailock configuration has been created successfully." }), _jsx(Text, {}), _jsx(Text, { bold: true, color: "blue", children: "Next steps:" }), _jsx(Text, { children: "1. \uD83D\uDD12 Lock your sensitive files: " }), _jsx(Text, { color: "gray", children: " ailock lock" }), _jsx(Text, {}), _jsx(Text, { children: "2. \uD83E\uDE9D Install Git protection: " }), _jsx(Text, { color: "gray", children: " ailock install-hooks" }), _jsx(Text, {}), _jsx(Text, { children: "3. \uD83D\uDCCA Check status anytime: " }), _jsx(Text, { color: "gray", children: " ailock status" }), _jsx(Text, {}), _jsx(Text, { color: "gray", children: "Exiting in 2 seconds..." })] })); } return null; }; //# sourceMappingURL=InitWizard.js.map