Lo que bloqueaba la fase 4 era el cliente, no las rutas: el catálogo viajaba en el paquete de JavaScript y las tarjetas, el carrito, la cuenta y el reproductor lo consultaban por su cuenta. Baja por `page.data` desde el layout —veintiún kilobytes, medidos, menos de lo que ocupaba en el paquete— y `$lib/catalogo/cliente.svelte` lo ata a las mismas consultas que usa el servidor. La otra opción era pasar por props lo que cada componente busca solo, y eso obligaba a tocar la compra, el carrito y el reproductor a la vez. Siete rutas dejan de ser cargadores universales: música, estilo, álbum, canción, portada y las dos de etiquetas. La ficha del tema se resuelve entera en el servidor, incluida la letra, que se pide sola y no viaja con el catálogo. Faltaba dónde guardar dos textos: la introducción de cada estilo y las notas de cada disco eran el cuerpo de su Markdown y el volcado se quedó solo con el frontmatter. Migración 0010 y `npm run db:completar` los rellena. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>master
parent
771e97c4e5
commit
0b823d44b4
@ -0,0 +1,9 @@
|
||||
-- El texto de los estilos y de los discos.
|
||||
--
|
||||
-- La introducción de cada estilo y las notas de cada disco eran el cuerpo de
|
||||
-- su Markdown, y el volcado se quedó solo con el frontmatter: no había columna
|
||||
-- donde ponerlas. Se vio al ir a cambiar las rutas, que las pedían como
|
||||
-- componente compilado.
|
||||
|
||||
ALTER TABLE "album" ADD COLUMN "cuerpo" text DEFAULT '' NOT NULL;--> statement-breakpoint
|
||||
ALTER TABLE "estilo" ADD COLUMN "cuerpo" text DEFAULT '' NOT NULL;
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* El catálogo en el navegador.
|
||||
*
|
||||
* Las mismas consultas de `./consultas`, atadas a lo que baja por
|
||||
* `page.data.catalogo`. Antes venían de `$lib/content`, que cargaba los
|
||||
* archivos al construir y por eso podía consultarse desde cualquier parte sin
|
||||
* pedir nada: el catálogo entero viajaba en el paquete de JavaScript.
|
||||
*
|
||||
* Con el catálogo en la base eso deja de valer, y hay dos formas de arreglarlo:
|
||||
* que cada componente reciba por props lo que hoy busca solo, o que el catálogo
|
||||
* baje una vez y siga estando a mano. Se eligió lo segundo porque son
|
||||
* veintiún kilobytes —menos de lo que ocupaba en el paquete— y porque lo
|
||||
* primero obligaba a tocar la compra, el carrito y el reproductor a la vez.
|
||||
*
|
||||
* Es `.svelte.ts` porque `page` es estado con runes: lo que se lee aquí dentro
|
||||
* es reactivo donde se use.
|
||||
*/
|
||||
|
||||
import { page } from '$app/state';
|
||||
import * as q from './consultas';
|
||||
import type { Catalogo } from './consultas';
|
||||
import type { Cancion } from '$lib/types';
|
||||
|
||||
const VACIO: Catalogo = { estilos: [], albumes: [], canciones: [] };
|
||||
|
||||
/**
|
||||
* Lo que haya bajado, o nada.
|
||||
*
|
||||
* El vacío no es un caso hipotético: la página de espera no carga catálogo, y
|
||||
* antes de que resuelva el `load` de la primera navegación tampoco hay. Sin
|
||||
* este respaldo, una tarjeta reventaba en vez de pintarse sin portada.
|
||||
*/
|
||||
function cat(): Catalogo {
|
||||
return (page.data.catalogo as Catalogo | undefined) ?? VACIO;
|
||||
}
|
||||
|
||||
export const estilos = () => cat().estilos;
|
||||
export const albumes = () => cat().albumes;
|
||||
export const canciones = () => cat().canciones;
|
||||
|
||||
export const obtenerEstilo = (slug: string) => q.obtenerEstilo(cat(), slug);
|
||||
export const estiloPrincipal = () => q.estiloPrincipal(cat());
|
||||
export const obtenerAlbum = (slug: string) => q.obtenerAlbum(cat(), slug);
|
||||
export const obtenerCancion = (slug: string) => q.obtenerCancion(cat(), slug);
|
||||
export const albumesDeEstilo = (estiloSlug: string) => q.albumesDeEstilo(cat(), estiloSlug);
|
||||
export const estilosConObra = () => q.estilosConObra(cat());
|
||||
export const etiquetas = () => q.etiquetas(cat());
|
||||
export const etiquetasDeEstilo = (estiloSlug: string, cuantas = 4) =>
|
||||
q.etiquetasDeEstilo(cat(), estiloSlug, cuantas);
|
||||
export const obtenerEtiqueta = (slug: string) => q.obtenerEtiqueta(cat(), slug);
|
||||
export const portadaDeCancion = (cancion: Cancion) => q.portadaDeCancion(cat(), cancion);
|
||||
|
||||
/* Estas dos no necesitan catálogo: son de la propia canción. */
|
||||
export const albumDeCancion = q.albumDeCancion;
|
||||
export const slugSingles = q.slugSingles;
|
||||
@ -0,0 +1,36 @@
|
||||
import {
|
||||
albumesDeEstilo,
|
||||
estiloPrincipal,
|
||||
estilosConObra,
|
||||
etiquetasDeEstilo,
|
||||
leerCatalogo,
|
||||
obtenerAlbum,
|
||||
obtenerEstiloConObra
|
||||
} from '$lib/server/catalogo';
|
||||
import { heroe } from '$lib/site';
|
||||
|
||||
/**
|
||||
* La portada cuenta el catálogo en tres pasos: el estilo principal, sus discos
|
||||
* y el resto de estilos. No lleva selecciones ni novedades: el catálogo es
|
||||
* pequeño y repetir las mismas tarjetas tres veces lo hace parecer aún más
|
||||
* corto de lo que es.
|
||||
*/
|
||||
export async function load() {
|
||||
const principal = await estiloPrincipal();
|
||||
const { albumes } = await leerCatalogo();
|
||||
|
||||
return {
|
||||
/** El disco que se pone en el tocadiscos de la cabecera. */
|
||||
heroe: (await obtenerAlbum(heroe.album)) ?? (await obtenerAlbum(albumes[0]?.slug ?? '')),
|
||||
|
||||
bloquePrincipal: principal ? await obtenerEstiloConObra(principal.slug) : undefined,
|
||||
/** De qué se habla en el estilo principal, sacado de sus temas. */
|
||||
etiquetasPrincipal: principal ? await etiquetasDeEstilo(principal.slug, 6) : [],
|
||||
|
||||
/** Lo demás, como tarjetas: cuánto hay en cada uno y de qué va. */
|
||||
otrosBloques: (await estilosConObra()).filter((b) => b.estilo.slug !== principal?.slug)
|
||||
};
|
||||
}
|
||||
|
||||
// Se importa para que quede claro que no hace falta: la portada no lo usa.
|
||||
void albumesDeEstilo;
|
||||
@ -1,32 +0,0 @@
|
||||
import {
|
||||
albumes,
|
||||
estiloPrincipal,
|
||||
estilosConObra,
|
||||
etiquetasDeEstilo,
|
||||
obtenerAlbum,
|
||||
obtenerEstiloConObra
|
||||
} from '$lib/content';
|
||||
import { heroe } from '$lib/site';
|
||||
|
||||
/**
|
||||
* La portada cuenta el catalogo en tres pasos: el estilo principal, sus discos
|
||||
* y el resto de estilos. No lleva selecciones ni novedades: el catalogo es
|
||||
* pequeno y repetir las mismas tarjetas tres veces lo hace parecer aun mas
|
||||
* corto de lo que es.
|
||||
*/
|
||||
export function load() {
|
||||
const principal = estiloPrincipal();
|
||||
const bloquePrincipal = principal ? obtenerEstiloConObra(principal.slug) : undefined;
|
||||
|
||||
return {
|
||||
/** El disco que se pone en el tocadiscos de la cabecera. */
|
||||
heroe: obtenerAlbum(heroe.album) ?? obtenerAlbum(albumes[0]?.slug ?? ''),
|
||||
|
||||
bloquePrincipal,
|
||||
/** De que se habla en el estilo principal, sacado de sus temas. */
|
||||
etiquetasPrincipal: principal ? etiquetasDeEstilo(principal.slug, 6) : [],
|
||||
|
||||
/** Lo demas, como tarjetas: cuanto hay en cada uno y de que va. */
|
||||
otrosBloques: estilosConObra().filter((b) => b.estilo.slug !== principal?.slug)
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { notasDeAlbum, obtenerAlbum, obtenerEstilo } from '$lib/server/catalogo';
|
||||
|
||||
export async function load({ params }) {
|
||||
const album = await obtenerAlbum(params.slug);
|
||||
if (!album) error(404, 'Ese album no existe.');
|
||||
|
||||
return {
|
||||
album,
|
||||
estilo: await obtenerEstilo(album.estilo),
|
||||
// Un álbum de singles no existe como fila, así que tampoco tiene notas.
|
||||
notas: album.sintetico ? '' : await notasDeAlbum(params.slug)
|
||||
};
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { cuerpoAlbum, obtenerAlbum, obtenerEstilo } from '$lib/content';
|
||||
|
||||
export function load({ params }) {
|
||||
const album = obtenerAlbum(params.slug);
|
||||
if (!album) error(404, 'Ese album no existe.');
|
||||
|
||||
return {
|
||||
album,
|
||||
estilo: obtenerEstilo(album.estilo),
|
||||
// Un album de singles no tiene archivo propio, asi que tampoco notas.
|
||||
Notas: album.sintetico ? undefined : cuerpoAlbum(params.slug)
|
||||
};
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import {
|
||||
albumDeCancion,
|
||||
cuerpoCancion,
|
||||
obtenerAlbum,
|
||||
obtenerCancion,
|
||||
obtenerEstilo,
|
||||
portadaDeCancion
|
||||
} from '$lib/content';
|
||||
|
||||
export function load({ params, data }) {
|
||||
const cancion = obtenerCancion(params.slug);
|
||||
if (!cancion) error(404, 'Ese tema no existe.');
|
||||
|
||||
// El album completo hace de contexto de reproduccion: darle al play aqui
|
||||
// deja sonando el disco entero, no solo este tema. En un single suelto, el
|
||||
// contexto es el album de singles de su estilo.
|
||||
const album = obtenerAlbum(albumDeCancion(cancion));
|
||||
const hermanas = album?.canciones ?? [cancion];
|
||||
const posicion = hermanas.findIndex((c) => c.slug === cancion.slug);
|
||||
|
||||
return {
|
||||
// Las valoraciones vienen de `+page.server.ts`; lo demas, del catalogo.
|
||||
...data,
|
||||
cancion,
|
||||
album,
|
||||
estilo: obtenerEstilo(cancion.estilo),
|
||||
portada: portadaDeCancion(cancion),
|
||||
hermanas,
|
||||
anterior: posicion > 0 ? hermanas[posicion - 1] : undefined,
|
||||
siguiente: posicion < hermanas.length - 1 ? hermanas[posicion + 1] : undefined,
|
||||
/** Cuerpo del Markdown: la letra, o las notas si es instrumental. */
|
||||
Cuerpo: cuerpoCancion(params.slug)
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
import { etiquetas } from '$lib/server/catalogo';
|
||||
|
||||
export async function load() {
|
||||
return { etiquetas: await etiquetas() };
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import { etiquetas } from '$lib/content';
|
||||
|
||||
export function load() {
|
||||
return { etiquetas: etiquetas() };
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { obtenerEtiqueta } from '$lib/server/catalogo';
|
||||
|
||||
export async function load({ params }) {
|
||||
const etiqueta = await obtenerEtiqueta(params.etiqueta);
|
||||
if (!etiqueta) error(404, 'Esa etiqueta no existe.');
|
||||
|
||||
return { etiqueta };
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { obtenerEtiqueta } from '$lib/content';
|
||||
|
||||
export function load({ params }) {
|
||||
const etiqueta = obtenerEtiqueta(params.etiqueta);
|
||||
if (!etiqueta) error(404, 'Esa etiqueta no existe.');
|
||||
|
||||
return { etiqueta };
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { estilosConObra } from '$lib/server/catalogo';
|
||||
|
||||
/**
|
||||
* Los estilos se cargan una vez para toda la sección: la portada de música los
|
||||
* necesita para pintar los bloques y cada página de estilo, para la barra
|
||||
* lateral. Al resolverlo aquí, cambiar de estilo no vuelve a calcularlos.
|
||||
*/
|
||||
export async function load() {
|
||||
return { bloques: await estilosConObra() };
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
import { estilosConObra } from '$lib/content';
|
||||
|
||||
/**
|
||||
* Los estilos se cargan una vez para toda la seccion: la portada de musica los
|
||||
* necesita para pintar los bloques y cada pagina de estilo, para la barra
|
||||
* lateral. Al resolverlo aqui, cambiar de estilo no vuelve a calcularlos.
|
||||
*/
|
||||
export function load() {
|
||||
return { bloques: estilosConObra() };
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import { estilosConObra } from '$lib/content';
|
||||
|
||||
export function load() {
|
||||
return { bloques: estilosConObra() };
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { obtenerEstiloConObra, textoDeEstilo } from '$lib/server/catalogo';
|
||||
|
||||
export async function load({ params }) {
|
||||
const bloque = await obtenerEstiloConObra(params.estilo);
|
||||
if (!bloque) error(404, 'Ese estilo no existe.');
|
||||
|
||||
// El texto llega compuesto: antes era un componente que compilaba mdsvex.
|
||||
return { bloque, introduccion: await textoDeEstilo(params.estilo) };
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { cuerpoEstilo, obtenerEstiloConObra } from '$lib/content';
|
||||
|
||||
export function load({ params }) {
|
||||
const bloque = obtenerEstiloConObra(params.estilo);
|
||||
if (!bloque) error(404, 'Ese estilo no existe.');
|
||||
|
||||
return {
|
||||
bloque,
|
||||
/** Texto introductorio del estilo; el cuerpo del .md, si lo tiene. */
|
||||
Introduccion: cuerpoEstilo(params.estilo)
|
||||
};
|
||||
}
|
||||
Loading…
Reference in new issue