ailock
Version:
AI-Proof File Guard - Protect sensitive files from accidental AI modifications
185 lines • 10.7 kB
JavaScript
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