'use strict'; /* ─────────────────────────────────────────────────────────────────────────── update_textbook_authors.js Приводит метаданные учебников к политике «все учебники наши»: • колонка textbooks.author → 'LearnSpace' (у всех учебников и их глав); • в textbooks.description убирается оборот «по учебнику <автор>:» → «:». Миграции 004/008/017–027/031/038/049/050 уже применены к БД с фамилиями сторонних авторов — их исходники почищены, но ЖИВУЮ БД правит этот идемпотентный скрипт. Запуск: node backend/scripts/update_textbook_authors.js # DRY-RUN (по умолчанию) node backend/scripts/update_textbook_authors.js --apply # запись в БД ⚠️ Массовую запись в БД запускает ПОЛЬЗОВАТЕЛЬ вручную. Без --apply ничего не пишется. ─────────────────────────────────────────────────────────────────────────── */ const { DatabaseSync } = require('node:sqlite'); const path = require('path'); const APPLY = process.argv.includes('--apply'); const AUTHOR = 'LearnSpace'; const DB = path.join(__dirname, '..', 'data', 'learnspace.db'); const stripDesc = d => (d ? d.replace(/ по учебнику [^:]*:/g, ':') : d); const db = new DatabaseSync(DB); // есть ли таблица/колонки const cols = db.prepare(`PRAGMA table_info(textbooks)`).all().map(c => c.name); if (!cols.includes('author')) { console.error('✗ В таблице textbooks нет колонки author. Прерывание.'); db.close(); process.exit(1); } const rows = db.prepare(`SELECT id, slug, author, description FROM textbooks`).all(); const changes = []; for (const r of rows) { const newDesc = stripDesc(r.description); const authorChange = (r.author || '') !== AUTHOR; const descChange = newDesc !== r.description; if (authorChange || descChange) changes.push({ id: r.id, slug: r.slug, oldAuthor: r.author, authorChange, descChange, newDesc }); } console.log(`\n=== update_textbook_authors (учебников: ${rows.length}) ===`); console.log(`Режим: ${APPLY ? 'APPLY (запись)' : 'DRY-RUN (только показ)'}\n`); console.log(`Под изменение: ${changes.length}`); for (const c of changes) { const tags = [c.authorChange ? `author: ${c.oldAuthor || '∅'} → ${AUTHOR}` : null, c.descChange ? 'описание: убран «по учебнику …»' : null].filter(Boolean).join('; '); console.log(` ${String(c.slug).padEnd(20)} ${tags}`); } if (!changes.length) { console.log('\nНечего менять — БД уже чистая.'); db.close(); process.exit(0); } if (!APPLY) { console.log('\nDRY-RUN: ничего не записано. Для записи: node backend/scripts/update_textbook_authors.js --apply\n'); db.close(); process.exit(0); } const upd = db.prepare(`UPDATE textbooks SET author = ?, description = ? WHERE id = ?`); let n = 0; db.exec('BEGIN'); try { for (const c of changes) { upd.run(AUTHOR, c.newDesc, c.id); n++; } db.exec('COMMIT'); console.log(`\n✓ Обновлено строк: ${n}. Все учебники → author='${AUTHOR}', обороты «по учебнику …» убраны.\n`); } catch (e) { db.exec('ROLLBACK'); console.error('\n✗ Ошибка записи, откат:', e.message); process.exitCode = 1; } db.close();