/
threed
/
claud-web
Обзор
Документация
Войти
/
threed
/
claud-web
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
lib/setup.js
99 строк
3 KB
threed
Claud Web: веб-терминал Claude Code — tmux-вкладки, мультипроект, мобильная версия
03 авг 2026, 20:30
03 авг 2026, 20:30
710eb6a
Код
Авторство
О чём код?
/** * Мастер первичной настройки: спрашивает логин/пароль/порт и пишет .env. * Запускается автоматически при первом старте (если .env нет) или вручную: * npm run setup */ const fs = require('fs'); const path = require('path'); const readline = require('readline'); const crypto = require('crypto'); const ENV_PATH = path.join(__dirname, '..', '.env'); function ask(rl, question, def) { const hint = def ? ` [${def}]` : ''; return new Promise(resolve => { rl.question(`${question}${hint}: `, answer => resolve(answer.trim() || def || '')); }); } /** Вопрос со скрытым вводом (пароль не отображается в терминале). */ function askHidden(rl, question) { return new Promise(resolve => { const onData = char => { const s = String(char); if (s === '\n' || s === '\r' || s === '') { process.stdin.removeListener('data', onData); } else { // затираем введённый символ readline.moveCursor(process.stdout, -s.length, 0); process.stdout.write('*'.repeat(s.length)); } }; process.stdin.on('data', onData); rl.question(`${question}: `, answer => { process.stdin.removeListener('data', onData); resolve(answer.trim()); }); }); } async function runSetup() { if (!process.stdin.isTTY) { throw new Error( 'Не настроены логин/пароль, а интерактивный ввод недоступен.\n' + 'Создайте файл .env вручную по образцу .env.example и перезапустите.' ); } console.log(''); console.log('=== Claud Web — первичная настройка ==='); console.log('Настройки сохранятся в .env (можно менять и вручную).'); console.log(''); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const username = await ask(rl, 'Логин для входа', 'admin'); let password = await askHidden(rl, 'Пароль для входа (Enter — сгенерировать)'); let generated = false; if (!password) { password = crypto.randomBytes(12).toString('base64url'); generated = true; } const port = await ask(rl, 'Порт сервиса', '3777'); rl.close(); const env = `PORT=${port} AUTH_USERNAME=${username} AUTH_PASSWORD=${password} CLAUDE_CMD=claude --dangerously-skip-permissions `; fs.writeFileSync(ENV_PATH, env, { mode: 0o600 }); console.log(''); console.log(`✅ Настройки сохранены в ${ENV_PATH}`); if (generated) { console.log(`🔑 Сгенерированный пароль: ${password}`); console.log(' Сохраните его — он понадобится для входа.'); } console.log(''); // Подхватываем без перезапуска процесса process.env.PORT = port; process.env.AUTH_USERNAME = username; process.env.AUTH_PASSWORD = password; process.env.CLAUDE_CMD = process.env.CLAUDE_CMD || 'claude --dangerously-skip-permissions'; return { username, port }; } module.exports = { runSetup, ENV_PATH }; if (require.main === module) { runSetup().catch(err => { console.error('Ошибка настройки:', err.message); process.exit(1); }); }