#!/usr/bin/env node import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; import chalk from 'chalk'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Configuration const NEW_PIPE_OUTPUT = path.join(__dirname, 'output'); const PUBLIC_DIR = path.join(__dirname, '../../../public'); const PUBLIC_DATA_DIR = path.join(PUBLIC_DIR, 'data'); // Fichiers à copier avec leurs destinations const FILES_TO_COPY = [ { source: 'data/typography_data.json', destination: 'data/typography_data.json', description: 'Données UMAP avec embeddings' }, // Plus besoin de mapping - utilisation directe des IDs { source: 'sprites/font-sprite.svg', destination: 'data/font-sprite.svg', description: 'Sprite SVG avec tous les symboles' } ]; // Dossiers à copier const DIRECTORIES_TO_COPY = [ { source: 'svgs', destination: 'data/sentences', description: 'Sentences SVG individuelles', filter: '*_sentence.svg' }, { source: 'svgs', destination: 'data/char', description: 'SVGs de la lettre A', filter: '*_a.svg' } ]; /** * Copie un fichier avec gestion d'erreurs */ async function copyFile(sourcePath, destPath, description) { try { await fs.copyFile(sourcePath, destPath); console.log(chalk.green(`✅ ${description}`)); console.log(chalk.blue(` 📁 ${path.relative(PUBLIC_DIR, destPath)}`)); // Afficher la taille du fichier const stats = await fs.stat(destPath); const sizeKB = (stats.size / 1024).toFixed(1); console.log(chalk.gray(` 📊 ${sizeKB} KB\n`)); return true; } catch (error) { console.error(chalk.red(`❌ Error during la copie de ${description}:`), error.message); return false; } } /** * Copie un dossier avec filtrage */ async function copyDirectory(sourceDir, destDir, description, filter) { try { // Créer le dossier de destination await fs.mkdir(destDir, { recursive: true }); // Lire les fichiers source const files = await fs.readdir(sourceDir); const filteredFiles = files.filter(file => { if (filter === '*_sentence.svg') { return file.endsWith('_sentence.svg'); } if (filter === '*_a.svg') { return file.endsWith('_a.svg'); } return true; }); console.log(chalk.blue(`🔄 ${description}...`)); console.log(chalk.cyan(` 📁 ${filteredFiles.length} fichiers à copier`)); let copiedCount = 0; let errorCount = 0; for (const file of filteredFiles) { const sourcePath = path.join(sourceDir, file); const destPath = path.join(destDir, file); try { await fs.copyFile(sourcePath, destPath); copiedCount++; if (copiedCount % 100 === 0) { console.log(chalk.gray(` 📋 Copié ${copiedCount}/${filteredFiles.length} fichiers...`)); } } catch (error) { errorCount++; console.log(chalk.red(`❌ Erreur copie ${file}: ${error.message}`)); } } console.log(chalk.green(`✅ ${description}`)); console.log(chalk.blue(` 📁 ${path.relative(PUBLIC_DIR, destDir)}`)); console.log(chalk.cyan(` 📊 ${copiedCount} fichiers copiés, ${errorCount} erreurs\n`)); return { success: true, copied: copiedCount, errors: errorCount }; } catch (error) { console.error(chalk.red(`❌ Erreur lors de la copie du dossier ${description}:`), error.message); return { success: false, copied: 0, errors: 1 }; } } /** * Vérifie qu'un fichier source existe */ async function checkSourceFile(sourcePath, description) { try { await fs.access(sourcePath); return true; } catch { console.error(chalk.red(`❌ Missing source file: ${description}`)); console.error(chalk.gray(` 📁 ${sourcePath}\n`)); return false; } } /** * Crée le dossier de destination si nécessaire */ async function ensureDestinationDir(destPath) { const destDir = path.dirname(destPath); try { await fs.access(destDir); } catch { await fs.mkdir(destDir, { recursive: true }); console.log(chalk.yellow(`📁 Directory created: ${destDir}`)); } } /** * Affiche les statistiques des fichiers copiés */ async function displayStats() { console.log(chalk.cyan('📊 Statistics des fichiers copiés:\n')); for (const file of FILES_TO_COPY) { const destPath = path.join(PUBLIC_DIR, file.destination); try { const stats = await fs.stat(destPath); const sizeKB = (stats.size / 1024).toFixed(1); console.log(chalk.white(` ${file.destination}: ${sizeKB} KB`)); } catch { console.log(chalk.red(` ${file.destination}: fichier non trouvé`)); } } console.log(''); } /** * Affiche un résumé des fichiers existants dans public */ async function showExistingFiles() { console.log(chalk.blue('📋 Fichiers existants dans public:\n')); try { const publicFiles = await fs.readdir(PUBLIC_DIR); const fontFiles = publicFiles.filter(file => file.includes('font') || file.includes('typography') || file.includes('sprite') ); if (fontFiles.length > 0) { for (const file of fontFiles.sort()) { const filePath = path.join(PUBLIC_DIR, file); try { const stats = await fs.stat(filePath); const sizeKB = (stats.size / 1024).toFixed(1); console.log(chalk.gray(` ${file} (${sizeKB} KB)`)); } catch { console.log(chalk.gray(` ${file}`)); } } } else { console.log(chalk.gray(' Aucun fichier de police trouvé')); } console.log(''); } catch (error) { console.error(chalk.red('❌ Error during la lecture du dossier public:'), error.message); } } /** * Supprime les anciennes données */ async function cleanupOldData() { console.log(chalk.blue('🧹 Nettoyage des anciennes données...')); try { // Supprimer le dossier data s'il existe try { await fs.rm(PUBLIC_DATA_DIR, { recursive: true, force: true }); console.log(chalk.green(`✅ Ancien dossier data supprimé: ${PUBLIC_DATA_DIR}`)); } catch { console.log(chalk.gray(`📁 Dossier data n'existait pas`)); } // Supprimer les anciens fichiers dans public const oldFiles = [ 'typography_data_new.json', 'font-sprite-mapping.json', // Supprimer l'ancien mapping 'font-sprite-mapping-new.json', 'font-sprite-new.svg' ]; for (const file of oldFiles) { const filePath = path.join(PUBLIC_DIR, file); try { await fs.unlink(filePath); console.log(chalk.green(`✅ Ancien fichier supprimé: ${file}`)); } catch { console.log(chalk.gray(`📁 Fichier ${file} n'existait pas`)); } } console.log(''); } catch (error) { console.error(chalk.red('❌ Erreur lors du nettoyage:'), error.message); throw error; } } /** * Fonction principale */ async function main() { console.log(chalk.blue.bold('📋 Copying files de données vers l\'application\n')); try { // Vérifier que le dossier public existe try { await fs.access(PUBLIC_DIR); console.log(chalk.green(`✅ Dossier public trouvé: ${PUBLIC_DIR}`)); } catch { throw new Error(`Dossier public non trouvé: ${PUBLIC_DIR}`); } // Vérifier que le dossier output existe try { await fs.access(NEW_PIPE_OUTPUT); console.log(chalk.green(`✅ Dossier output trouvé: ${NEW_PIPE_OUTPUT}\n`)); } catch { throw new Error(`Dossier output non trouvé: ${NEW_PIPE_OUTPUT}`); } // Nettoyer les anciennes données await cleanupOldData(); // Afficher les fichiers existants await showExistingFiles(); // Copier chaque fichier let successCount = 0; let totalCount = FILES_TO_COPY.length; console.log(chalk.cyan('🔄 Copie des fichiers...\n')); for (const file of FILES_TO_COPY) { const sourcePath = path.join(NEW_PIPE_OUTPUT, file.source); const destPath = path.join(PUBLIC_DIR, file.destination); // Check that file source existe if (!(await checkSourceFile(sourcePath, file.description))) { continue; } // Create directory de destination si nécessaire await ensureDestinationDir(destPath); // Copy file if (await copyFile(sourcePath, destPath, file.description)) { successCount++; } } // Copier les dossiers console.log(chalk.cyan('🔄 Copie des dossiers...\n')); for (const dir of DIRECTORIES_TO_COPY) { const sourceDir = path.join(NEW_PIPE_OUTPUT, dir.source); const destDir = path.join(PUBLIC_DIR, dir.destination); // Check that source directory existe try { await fs.access(sourceDir); } catch { console.log(chalk.red(`❌ Dossier source manquant: ${dir.description}`)); console.log(chalk.gray(` 📁 ${sourceDir}\n`)); continue; } // Copy directory const result = await copyDirectory(sourceDir, destDir, dir.description, dir.filter); if (result.success) { successCount++; totalCount++; } } // Afficher les statistiques finales await displayStats(); console.log(chalk.green.bold('🎉 Copie terminée !')); console.log(chalk.cyan(`📊 Summary:`)); console.log(chalk.white(` - ${successCount}/${totalCount} fichiers copiés avec succès`)); console.log(chalk.white(` - Destination: ${PUBLIC_DATA_DIR}`)); if (successCount === totalCount) { console.log(chalk.green('\n✅ Tous les fichiers ont été copiés avec succès !')); console.log(chalk.blue('💡 Les nouveaux fichiers sont maintenant disponibles dans public/data/')); console.log(chalk.blue('📁 Structure:')); console.log(chalk.white(' - public/data/typography_data.json')); console.log(chalk.white(' - public/data/font-sprite.svg')); console.log(chalk.white(' - public/data/sentences/')); console.log(chalk.white(' - public/data/char/')); } else { console.log(chalk.yellow(`\n⚠️ ${totalCount - successCount} fichier(s) n'ont pas pu être copiés.`)); } } catch (error) { console.error(chalk.red('💥 Erreur fatale:'), error.message); process.exit(1); } } // Lancer le script main();