Web de Senza Paura: catálogo, taller, blog y tienda
Sitio del letrista y compositor, con SvelteKit 2 y Svelte 5.
El catálogo es contenido, no base de datos: estilos, álbumes, canciones y
capítulos son Markdown en `src/content/`, validados al compilar y compilados
dentro del bundle, así que recorrer la música no hace ni una consulta. La base
de datos guarda solo lo que generan las personas: cuentas, carritos, pedidos,
compras, valoraciones y favoritos.
Lo que hay:
- Música agrupada por estilos, con página propia para cada estilo, álbum y
tema, buscador y tabla ordenable.
- Reproductor persistente que sobrevive a la navegación. Suena un fragmento;
el archivo completo solo se obtiene comprando.
- Taller de letras: los principios del oficio y una ficha de creación por
estilo hispanoamericano.
- Blog con feed RSS, y etiquetas que cruzan blog y catálogo.
- Tienda con cuentas por código de correo, carrito, Stripe y descargas
protegidas.
- Panel de contenido en `/admin` que escribe los mismos Markdown.
- Tema oscuro de marca y su inversión clara, aplicado antes de pintar.
Lo que falta y no es código: las claves de Stripe y de correo, el tratamiento
del IVA, las páginas de condiciones y privacidad, y el material real. Las
canciones de ejemplo son inventadas y están para sustituirse; el audio son
marcadores salvo un tema.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 month ago
|
|
|
{
|
|
|
|
|
"name": "senzapaura",
|
|
|
|
|
"private": true,
|
|
|
|
|
"version": "0.0.1",
|
|
|
|
|
"type": "module",
|
|
|
|
|
"scripts": {
|
|
|
|
|
"dev": "vite dev",
|
|
|
|
|
"build": "vite build",
|
|
|
|
|
"preview": "vite preview",
|
|
|
|
|
"prepare": "svelte-kit sync || echo ''",
|
|
|
|
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
|
|
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
|
|
|
"lint": "prettier --check . && eslint .",
|
|
|
|
|
"format": "prettier --write .",
|
|
|
|
|
"test:unit": "vitest",
|
|
|
|
|
"test": "npm run test:unit -- --run && npm run test:e2e",
|
|
|
|
|
"test:e2e": "playwright install && node scripts/construir.mjs && playwright test",
|
|
|
|
|
"db:push": "drizzle-kit push",
|
|
|
|
|
"db:generate": "drizzle-kit generate",
|
|
|
|
|
"db:migrate": "drizzle-kit migrate",
|
|
|
|
|
"db:studio": "drizzle-kit studio",
|
|
|
|
|
"medios": "node scripts/medios.mjs",
|
|
|
|
|
"predev": "node scripts/medios.mjs",
|
Fase 2: el esquema entero en PostgreSQL
52 tablas nuevas, una vista y las guardas que Drizzle no sabe expresar. El
sitio sigue leyendo de los archivos: esto solo crea el sitio donde caben.
El esquema pasa de archivo a carpeta —con el catálogo dentro pasaría de
las dos mil líneas—, y el corte se hizo por rangos de línea para no
reescribir los comentarios que explican decisiones. Se comprobó que era un
no-op: «No schema changes, nothing to migrate».
Lo que Drizzle no genera va escrito a mano al final de la migración, y es
justo lo que impide que el modelo mienta: la clave foránea de las
versiones contra su propia tabla, dos columnas generadas y una clave
compuesta que impiden a la vez la versión de una versión y los ciclos, la
vista `cancion_principal`, el disparador que exige que el reparto de
autoría sume cien, el que impide ciclos en el linaje de géneros, y los
índices parciales del estilo principal y de la arista principal.
Y las guardas se comprueban intentando lo que deben rechazar, en
`scripts/db/comprobar-guardas.mjs`. Que una restricción exista en
`pg_constraint` no significa que impida nada.
Tres cosas que salieron de hacerlo y no de suponerlo:
- `creado_en` era obligatorio SIN valor por defecto en la base: lo ponía
JavaScript al insertar con Drizzle, así que cualquier INSERT escrito a
mano fallaba y la invariante la sostenía la aplicación, no la tabla.
Ahora es `defaultNow()`.
- `drizzle-kit migrate` se atasca con los cuerpos `$$` de plpgsql. La
migración se aplicó con `scripts/db/probar-migracion.mjs`, que además
dice en qué sentencia falla, y se anotó en su registro.
- Dos pruebas pasaban por el motivo equivocado: una por clave duplicada en
vez de por la suma, y otra porque un disparador aplazado no salta dentro
de un savepoint que nunca se cierra. Las dos corregidas; una guarda dada
por buena sin ejecutarse es peor que no tenerla.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
|
|
|
"prebuild": "node scripts/medios.mjs",
|
|
|
|
|
"db:guardas": "node --env-file=.env scripts/db/comprobar-guardas.mjs",
|
|
|
|
|
"db:probar": "node --env-file=.env scripts/db/probar-migracion.mjs"
|
Web de Senza Paura: catálogo, taller, blog y tienda
Sitio del letrista y compositor, con SvelteKit 2 y Svelte 5.
El catálogo es contenido, no base de datos: estilos, álbumes, canciones y
capítulos son Markdown en `src/content/`, validados al compilar y compilados
dentro del bundle, así que recorrer la música no hace ni una consulta. La base
de datos guarda solo lo que generan las personas: cuentas, carritos, pedidos,
compras, valoraciones y favoritos.
Lo que hay:
- Música agrupada por estilos, con página propia para cada estilo, álbum y
tema, buscador y tabla ordenable.
- Reproductor persistente que sobrevive a la navegación. Suena un fragmento;
el archivo completo solo se obtiene comprando.
- Taller de letras: los principios del oficio y una ficha de creación por
estilo hispanoamericano.
- Blog con feed RSS, y etiquetas que cruzan blog y catálogo.
- Tienda con cuentas por código de correo, carrito, Stripe y descargas
protegidas.
- Panel de contenido en `/admin` que escribe los mismos Markdown.
- Tema oscuro de marca y su inversión clara, aplicado antes de pintar.
Lo que falta y no es código: las claves de Stripe y de correo, el tratamiento
del IVA, las páginas de condiciones y privacidad, y el material real. Las
canciones de ejemplo son inventadas y están para sustituirse; el audio son
marcadores salvo un tema.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 month ago
|
|
|
},
|
|
|
|
|
"devDependencies": {
|
|
|
|
|
"@eslint/js": "^10.0.1",
|
|
|
|
|
"@playwright/test": "^1.60.0",
|
|
|
|
|
"@sveltejs/adapter-node": "^5.5.4",
|
|
|
|
|
"@sveltejs/kit": "^2.63.0",
|
|
|
|
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
|
|
|
"@types/node": "^22",
|
|
|
|
|
"@types/pg": "^8.23.1",
|
Web de Senza Paura: catálogo, taller, blog y tienda
Sitio del letrista y compositor, con SvelteKit 2 y Svelte 5.
El catálogo es contenido, no base de datos: estilos, álbumes, canciones y
capítulos son Markdown en `src/content/`, validados al compilar y compilados
dentro del bundle, así que recorrer la música no hace ni una consulta. La base
de datos guarda solo lo que generan las personas: cuentas, carritos, pedidos,
compras, valoraciones y favoritos.
Lo que hay:
- Música agrupada por estilos, con página propia para cada estilo, álbum y
tema, buscador y tabla ordenable.
- Reproductor persistente que sobrevive a la navegación. Suena un fragmento;
el archivo completo solo se obtiene comprando.
- Taller de letras: los principios del oficio y una ficha de creación por
estilo hispanoamericano.
- Blog con feed RSS, y etiquetas que cruzan blog y catálogo.
- Tienda con cuentas por código de correo, carrito, Stripe y descargas
protegidas.
- Panel de contenido en `/admin` que escribe los mismos Markdown.
- Tema oscuro de marca y su inversión clara, aplicado antes de pintar.
Lo que falta y no es código: las claves de Stripe y de correo, el tratamiento
del IVA, las páginas de condiciones y privacidad, y el material real. Las
canciones de ejemplo son inventadas y están para sustituirse; el audio son
marcadores salvo un tema.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 month ago
|
|
|
"@vitest/browser-playwright": "^4.1.8",
|
|
|
|
|
"drizzle-kit": "^0.31.10",
|
|
|
|
|
"eslint": "^10.4.1",
|
|
|
|
|
"eslint-config-prettier": "^10.1.8",
|
|
|
|
|
"eslint-plugin-svelte": "^3.19.0",
|
|
|
|
|
"globals": "^17.6.0",
|
|
|
|
|
"js-yaml": "^5.4.1",
|
|
|
|
|
"mdsvex": "^0.12.7",
|
|
|
|
|
"playwright": "^1.60.0",
|
|
|
|
|
"prettier": "^3.8.3",
|
|
|
|
|
"prettier-plugin-svelte": "^4.1.0",
|
|
|
|
|
"remark-breaks": "^4.0.0",
|
|
|
|
|
"svelte": "^5.56.1",
|
|
|
|
|
"svelte-check": "^4.6.0",
|
|
|
|
|
"typescript": "^6.0.3",
|
|
|
|
|
"typescript-eslint": "^8.60.1",
|
|
|
|
|
"vite": "^8.0.16",
|
|
|
|
|
"vitest": "^4.1.8",
|
|
|
|
|
"vitest-browser-svelte": "^2.1.1"
|
|
|
|
|
},
|
|
|
|
|
"dependencies": {
|
|
|
|
|
"drizzle-orm": "^0.45.2",
|
|
|
|
|
"pg": "^8.23.0",
|
Web de Senza Paura: catálogo, taller, blog y tienda
Sitio del letrista y compositor, con SvelteKit 2 y Svelte 5.
El catálogo es contenido, no base de datos: estilos, álbumes, canciones y
capítulos son Markdown en `src/content/`, validados al compilar y compilados
dentro del bundle, así que recorrer la música no hace ni una consulta. La base
de datos guarda solo lo que generan las personas: cuentas, carritos, pedidos,
compras, valoraciones y favoritos.
Lo que hay:
- Música agrupada por estilos, con página propia para cada estilo, álbum y
tema, buscador y tabla ordenable.
- Reproductor persistente que sobrevive a la navegación. Suena un fragmento;
el archivo completo solo se obtiene comprando.
- Taller de letras: los principios del oficio y una ficha de creación por
estilo hispanoamericano.
- Blog con feed RSS, y etiquetas que cruzan blog y catálogo.
- Tienda con cuentas por código de correo, carrito, Stripe y descargas
protegidas.
- Panel de contenido en `/admin` que escribe los mismos Markdown.
- Tema oscuro de marca y su inversión clara, aplicado antes de pintar.
Lo que falta y no es código: las claves de Stripe y de correo, el tratamiento
del IVA, las páginas de condiciones y privacidad, y el material real. Las
canciones de ejemplo son inventadas y están para sustituirse; el audio son
marcadores salvo un tema.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 month ago
|
|
|
"stripe": "^22.6.1"
|
|
|
|
|
}
|
|
|
|
|
}
|