El patrón Iterator recorre una colección sin exponer su estructura interna.
1. El Problema de Partida
getAllMdxFiles(dir) carga en memoria un array con todas las rutas .mdx del árbol de carpetas antes de devolverlo. Para operaciones como scripts/validate-content.js, que solo necesita validar uno a uno y puede detenerse en el primer error, cargar los cientos de archivos por adelantado es innecesario cuando la colección crezca mucho.
2. La Solución Iterator
// src/lib/MdxFileIterator.js
import fs from 'fs';
import path from 'path';
export class MdxFileIterator {
#stack;
constructor(rootDir) {
this.#stack = [rootDir];
}
hasNext() {
this.#advanceToFile();
return this.#stack.length > 0;
}
next() {
this.#advanceToFile();
return this.#stack.pop();
}
#advanceToFile() {
while (this.#stack.length > 0) {
const top = this.#stack[this.#stack.length - 1];
if (fs.statSync(top).isDirectory()) {
this.#stack.pop();
const entries = fs.readdirSync(top).map((e) => path.join(top, e));
this.#stack.push(...entries);
} else if (top.endsWith('.mdx')) {
return; // Archivo válido en la cima de la pila
} else {
this.#stack.pop(); // Descarta archivos no .mdx
}
}
}
}3. Uso — validación temprana sin cargar todo el árbol
// scripts/validate-content.js
import { MdxFileIterator } from '@/lib/MdxFileIterator';
const it = new MdxFileIterator('content/knowledge/es');
while (it.hasNext()) {
const file = it.next();
const error = validate(file);
if (error) { console.error(`❌ ${file}: ${error}`); process.exit(1); } // Corta al primer fallo
}4. Ventajas
- No carga todo el árbol de antemano: recorre carpeta a carpeta, solo lo necesario hasta encontrar un fallo.
- Detención temprana barata: validar y abortar en el primer error no exige haber listado los 300 archivos restantes.
- Misma interfaz que cualquier otro iterador (
hasNext()/next()), reutilizable en otros scripts.