You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/scripts/db/gancho-lib.mjs

59 lines
2.4 KiB

Vuelca el catálogo a PostgreSQL, y lo comprueba Los 48 archivos entran en la base: 18 canciones con sus 5 versiones como filas hermanas, 4 discos, 4 estilos, 8 géneros, 14 capítulos, 9 personas, 53 etiquetas, 2 entradas, 5 legales y una página. La web sigue leyendo de los archivos; esto solo llena el sitio donde caben. Reutiliza los analizadores del sitio en vez de leer el frontmatter otra vez. Es la decisión que sostiene todo lo demás: si un valor por defecto o una normalización cambian, cambian para los dos. Un segundo analizador «parecido» es lo que garantiza que un día la base y la web cuenten cosas distintas sin que nadie lo note. Todo en una transacción, y al final comprueba lo escrito contra lo leído —la letra de cada tema carácter a carácter— porque «no dio error» no es lo mismo que «está bien». Si no cuadra, deshace y dice qué falló. Y es idempotente: se puede lanzar las veces que haga falta sin duplicar nada, sin tocar cuentas, pedidos ni compras. Para poder reutilizar ese código desde Node hizo falta un gancho de resolución —`$lib`, imports sin extensión y un sustituto de `$app/paths`— y quitar una propiedad de parámetro de `ErrorDeContenido`: es sintaxis exclusiva de TypeScript y ningún cargador que solo borre tipos puede con ella. Y una corrección: el cuerpo del Markdown de una canción NO era un comentario, es la letra. Lo dije al revés en el documento del modelo y lo repetí varias veces. El campo `letra:` del frontmatter —que aparece en un solo archivo— son los créditos de quién la firma. Corregido en el documento, en el esquema, y quitada la columna `nota` que sobraba. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
/**
* El gancho de resolución para poder cargar código del sitio desde un script.
*
* Hace dos cosas que Vite hace y Node no:
*
* - `$lib/x` pasa a ser `src/lib/x`.
* - Los imports sin extensión —`./fields`, `$lib/utils/date`— encuentran su
* `.ts`. En ESM, Node exige la ruta completa; el código del proyecto se
* escribe como se escribe con un empaquetador delante.
*
* Existe para que el volcado pueda reutilizar los analizadores del sitio en
* lugar de copiarlos. Una copia «parecida» es lo que garantiza que un día la
* base y la web cuenten cosas distintas y nadie lo note.
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
const RAIZ_LIB = path.resolve('src/lib');
/**
* Los módulos que SvelteKit inyecta en tiempo de compilación y fuera de la
* aplicación no existen. Se sustituyen por lo mínimo que necesita el código que
* el volcado reutiliza; `$app/types` no aparece porque solo se importa como
* tipo y el borrado de tipos se lo lleva por delante.
*/
const SUSTITUTOS = {
El catálogo de la base ya es idéntico al de los archivos Antes de cambiar veinte rutas de sitio, poder demostrar que sale lo mismo. `npm run db:comparar` pone lado a lado las dieciocho canciones, los cuatro discos y los cuatro estilos, campo a campo, y dice dónde difieren con la ruta exacta —`dorina.registro.reparto[0].porcentaje`—. Confiar en que las pruebas de interfaz noten una diferencia de un año o de un porcentaje sería confiar de más: pintan lo que les den. La primera pasada encontró ciento y pico diferencias, y no eran del comparador: - **Ningún medio estaba enlazado.** El volcado del catálogo y el de archivos se hicieron por separado, así que las veintitrés canciones tenían `audio_id`, `muestra_id` y `portada_id` a nulo. La web habría dejado de reproducir en cuanto leyera de la base. No se vio al volcar porque aquello comprobaba las letras carácter a carácter —lo delicado— y no que las relaciones estuvieran puestas. - **Las etiquetas volvían en orden alfabético.** No es cosmético: la primera etiqueta de un tema dice de qué va y las de después matizan. Ahora `cancion_etiqueta` tiene `orden`. - **La nota de cada versión no tenía columna** donde caer. - El país de edición se guardaba en ninguna parte, y los cuatro discos se quedaron sin él. `scripts/db/completar-catalogo.mjs` ata esos cabos y es idempotente. Los alias de `medio` son de verdad y no la misma tabla dos veces: sin ellos Postgres devuelve la misma fila para el audio y para la portada. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
'$app/paths': path.resolve('scripts/db/app-paths.mjs'),
'$env/dynamic/private': path.resolve('scripts/db/env-privado.mjs')
Vuelca el catálogo a PostgreSQL, y lo comprueba Los 48 archivos entran en la base: 18 canciones con sus 5 versiones como filas hermanas, 4 discos, 4 estilos, 8 géneros, 14 capítulos, 9 personas, 53 etiquetas, 2 entradas, 5 legales y una página. La web sigue leyendo de los archivos; esto solo llena el sitio donde caben. Reutiliza los analizadores del sitio en vez de leer el frontmatter otra vez. Es la decisión que sostiene todo lo demás: si un valor por defecto o una normalización cambian, cambian para los dos. Un segundo analizador «parecido» es lo que garantiza que un día la base y la web cuenten cosas distintas sin que nadie lo note. Todo en una transacción, y al final comprueba lo escrito contra lo leído —la letra de cada tema carácter a carácter— porque «no dio error» no es lo mismo que «está bien». Si no cuadra, deshace y dice qué falló. Y es idempotente: se puede lanzar las veces que haga falta sin duplicar nada, sin tocar cuentas, pedidos ni compras. Para poder reutilizar ese código desde Node hizo falta un gancho de resolución —`$lib`, imports sin extensión y un sustituto de `$app/paths`— y quitar una propiedad de parámetro de `ErrorDeContenido`: es sintaxis exclusiva de TypeScript y ningún cargador que solo borre tipos puede con ella. Y una corrección: el cuerpo del Markdown de una canción NO era un comentario, es la letra. Lo dije al revés en el documento del modelo y lo repetí varias veces. El campo `letra:` del frontmatter —que aparece en un solo archivo— son los créditos de quién la firma. Corregido en el documento, en el esquema, y quitada la columna `nota` que sobraba. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
};
/** Prueba el archivo tal cual, con extensión, y como carpeta con índice. */
function primeroQueExista(base) {
const candidatos = [base, `${base}.ts`, `${base}.js`, `${base}.mjs`, path.join(base, 'index.ts')];
return candidatos.find((c) => fs.existsSync(c) && fs.statSync(c).isFile());
}
export function resolve(especificador, contexto, siguiente) {
if (SUSTITUTOS[especificador]) {
return { url: pathToFileURL(SUSTITUTOS[especificador]).href, shortCircuit: true };
}
if (especificador.startsWith('$lib/')) {
const encontrado = primeroQueExista(path.join(RAIZ_LIB, especificador.slice(5)));
if (!encontrado) throw new Error(`No encuentro ${especificador}`);
return { url: pathToFileURL(encontrado).href, shortCircuit: true };
}
// Relativo y sin extensión: se completa igual que haría el empaquetador.
if (especificador.startsWith('.') && !path.extname(especificador) && contexto.parentURL) {
const desde = path.dirname(fileURLToPath(contexto.parentURL));
const encontrado = primeroQueExista(path.resolve(desde, especificador));
if (encontrado) return { url: pathToFileURL(encontrado).href, shortCircuit: true };
}
return siguiente(especificador, contexto);
}

Powered by TurnKey Linux.