restore-book43.js 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Restore book 43 from local DB to production
  2. const mysql = require('../server/node_modules/mysql2/promise');
  3. const fs = require('fs');
  4. function esc(str) {
  5. if (str === null || str === undefined) return 'NULL';
  6. return "'" + String(str).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'";
  7. }
  8. function fmtDate(d) {
  9. if (!d) return null;
  10. // MySQL datetime format
  11. const dt = new Date(d);
  12. const pad = n => String(n).padStart(2, '0');
  13. return `${dt.getFullYear()}-${pad(dt.getMonth()+1)}-${pad(dt.getDate())} ${pad(dt.getHours())}:${pad(dt.getMinutes())}:${pad(dt.getSeconds())}`;
  14. }
  15. (async () => {
  16. const c = await mysql.createConnection('mysql://root:123456@localhost:3306/audio_book');
  17. const [books] = await c.execute('SELECT * FROM Book WHERE id = 43');
  18. const [chapters] = await c.execute('SELECT * FROM BookChapter WHERE bookId = 43');
  19. await c.end();
  20. if (books.length === 0) {
  21. console.error('Book 43 not found in local DB!');
  22. process.exit(1);
  23. }
  24. const b = books[0];
  25. const lines = [];
  26. // Insert Book with explicit id
  27. lines.push('-- Restore Book 43');
  28. lines.push('INSERT INTO Book (id, userId, title, subtitle, description, targetAudience, style, bookScale, totalChapters, estimatedWords, progress, isPublished, genStage, autoGenerateContent, autoGenerateAudio, voiceSpeed, outlineJson, bookAnalysis, createdAt, updatedAt) VALUES (');
  29. lines.push(' 43,');
  30. lines.push(' 1,');
  31. lines.push(' ' + esc(b.title) + ',');
  32. lines.push(' ' + esc(b.subtitle) + ',');
  33. lines.push(' ' + esc(b.description) + ',');
  34. lines.push(' ' + esc(b.targetAudience) + ',');
  35. lines.push(' ' + esc(b.style) + ',');
  36. lines.push(' ' + esc(b.bookScale) + ',');
  37. lines.push(' ' + b.totalChapters + ',');
  38. lines.push(' ' + b.estimatedWords + ',');
  39. lines.push(' ' + b.progress + ',');
  40. lines.push(' ' + (b.isPublished ? 1 : 0) + ',');
  41. lines.push(' ' + esc(b.genStage) + ',');
  42. lines.push(' ' + (b.autoGenerateContent ? 1 : 0) + ',');
  43. lines.push(' ' + (b.autoGenerateAudio ? 1 : 0) + ',');
  44. lines.push(' ' + b.voiceSpeed + ',');
  45. lines.push(' ' + esc(b.outlineJson) + ',');
  46. lines.push(' ' + esc(b.bookAnalysis) + ',');
  47. lines.push(' ' + esc(fmtDate(b.createdAt)) + ',');
  48. lines.push(' ' + esc(fmtDate(b.updatedAt)));
  49. lines.push(');');
  50. lines.push('');
  51. // Insert Chapters
  52. chapters.forEach(ch => {
  53. lines.push(`-- Restore Chapter ${ch.id}`);
  54. lines.push('INSERT INTO BookChapter (id, bookId, parentId, level, number, title, summary, keyPoints, estimatedWords, content, wordCount, genStage, audioUrl, audioDuration, isPublic, generatedAt) VALUES (');
  55. lines.push(' ' + ch.id + ',');
  56. lines.push(' ' + ch.bookId + ',');
  57. lines.push(' ' + ch.parentId + ',');
  58. lines.push(' ' + ch.level + ',');
  59. lines.push(' ' + ch.number + ',');
  60. lines.push(' ' + esc(ch.title) + ',');
  61. lines.push(' ' + esc(ch.summary) + ',');
  62. lines.push(' ' + esc(ch.keyPoints) + ',');
  63. lines.push(' ' + ch.estimatedWords + ',');
  64. lines.push(' ' + esc(ch.content) + ',');
  65. lines.push(' ' + ch.wordCount + ',');
  66. lines.push(' ' + esc(ch.genStage) + ',');
  67. lines.push(' ' + esc(ch.audioUrl) + ',');
  68. lines.push(' ' + ch.audioDuration + ',');
  69. lines.push(' ' + (ch.isPublic ? 1 : 0) + ',');
  70. lines.push(' ' + esc(fmtDate(ch.generatedAt)));
  71. lines.push(');');
  72. lines.push('');
  73. });
  74. // Also output as JSON for easier transfer
  75. const sql = lines.join('\n');
  76. console.log(sql);
  77. // Save to file
  78. fs.writeFileSync('scripts/restore-book43.sql', sql, 'utf-8');
  79. console.error('SQL saved to scripts/restore-book43.sql');
  80. })();