diff --git a/.env.example b/.env.example
index a00dc26..8793a5e 100644
--- a/.env.example
+++ b/.env.example
@@ -4,8 +4,8 @@ DATABASE_URL=postgresql://senza_paura_web:CLAVE@192.168.18.171:5432/senzapaura
# --- Audio -------------------------------------------------------------------
# Directorio privado con los archivos completos. NO debe servirse como estático:
-# es lo que se entrega solo a quien ha comprado. Los fragmentos de muestra viven
-# aparte, en static/muestras/, y esos sí son públicos.
+# es lo que se entrega solo a quien ha comprado. Las canciones completas de
+# escucha viven a menor calidad en static/escucha/ y son públicas.
MEDIA_DIR=./media/audio
# --- Pagos (Stripe) ----------------------------------------------------------
diff --git a/README.md b/README.md
index 090cf64..2a56773 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@ clásica, rock y pop melódico—, se escucha desde un **reproductor persistente
que no se corta al navegar, y se puede **comprar en packs de diez canciones**
que se entregan como descarga en MP3.
-El catálogo vive en Markdown dentro del repositorio: publicar una canción es
-añadir un archivo. La base de datos guarda solo lo que generan las personas que
-visitan la web —cuentas, carritos, pedidos y compras—.
+El catálogo y el contenido editorial viven en PostgreSQL. Los Markdown de
+`src/content` se conservan como fuente de importación y respaldo, pero el sitio
+público y el panel leen el modelo relacional.
## Estado
@@ -81,20 +81,22 @@ el botón de pagar avisa de que no hay pasarela. Sin clave de correo, en
desarrollo **el código de acceso se imprime por consola**, así que se puede
entrar en una cuenta sin configurar nada.
-| Comando | Qué hace |
-| --------------------- | --------------------------------------------- |
-| `npm run dev` | Servidor de desarrollo (panel en `/admin`) |
-| `npm run build` | Compila a `build/` (adapter-node) |
-| `npm run preview` | Sirve la compilación de producción en `:4173` |
-| `npm run check` | Comprobación de tipos |
-| `npm run lint` | Prettier + ESLint |
-| `npm run format` | Formatea el proyecto |
-| `npm run test:unit` | Tests unitarios y de componente (Vitest) |
-| `npm run test:e2e` | Compila y ejecuta los end-to-end (Playwright) |
-| `npm test` | Todo lo anterior |
-| `npm run db:generate` | Genera una migración a partir del esquema |
-| `npm run db:migrate` | Aplica las migraciones pendientes |
-| `npm run db:studio` | Abre el visor de la base de datos |
+| Comando | Qué hace |
+| ---------------------------------------- | ------------------------------------------------- |
+| `npm run dev` | Servidor de desarrollo (panel en `/admin`) |
+| `npm run build` | Compila a `build/` (adapter-node) |
+| `npm run preview` | Sirve la compilación de producción en `:4173` |
+| `npm run check` | Comprobación de tipos |
+| `npm run lint` | Prettier + ESLint |
+| `npm run format` | Formatea el proyecto |
+| `npm run test:unit` | Tests unitarios y de componente (Vitest) |
+| `npm run test:e2e` | Compila y ejecuta los end-to-end (Playwright) |
+| `npm test` | Todo lo anterior |
+| `npm run db:generate` | Genera una migración a partir del esquema |
+| `npm run db:migrate` | Aplica las migraciones pendientes |
+| `npm run db:migrate:check -- ` | Prueba migraciones y revierte la transacción |
+| `npm run db:auditar-musica` | Comprueba códigos, créditos y streams tras migrar |
+| `npm run db:studio` | Abre el visor de la base de datos |
## El panel
@@ -121,9 +123,8 @@ que se desincronizaran nadie se enteraría hasta que el panel guardara en una
columna que ya no está.
La portada del panel dice qué hay y qué falta —capítulos sin publicar, géneros
-sin ficha, marcas del glosario sin confirmar—, que es la pregunta que se hace
-quien entra. Desde ahí se editan los capítulos, las fichas de género y los
-prompts de IA.
+sin ficha, artistas incompletos y canciones sin audio de escucha—. Desde ahí se
+editan capítulos, géneros, artistas, créditos, versiones musicales y prompts.
### Los prompts
@@ -473,14 +474,17 @@ los principios a las fichas es cambiar de cosa, no seguir leyendo.
## Dónde va el audio
-Como el catálogo se vende, **el archivo completo no es público**:
+Cada grabación tiene representaciones técnicas distintas. La escucha pública
+contiene la canción completa a calidad reducida; el máster y la descarga de
+compra siguen siendo privados.
Todo va agrupado **por disco**, con el mismo nombre de carpeta en los tres
árboles:
```
-media/audio//NN-.mp3 archivo completo — privado, nunca se sirve
-static/muestras//NN-.mp3 fragmento — público, es lo que suena en la web
+media/audio//NN-.wav máster o descarga — privado
+static/escucha//NN-.mp3 canción completa a 96 kbps — pública
+static/muestras//NN-.mp3 fragmento antiguo — legado temporal
static/images//portada.jpg portada del disco
static/images//.jpg portada propia de un tema
static/images/sin-portada.svg reserva cuando no hay ninguna
@@ -491,7 +495,7 @@ del álbum «Singles» que se genera solo.
La `` del audio es lo que declara el campo `audio` de la canción, sin
barra inicial: `como-si-nada/01-como-si-nada.mp3`. De ahí salen la ruta privada
-y la de la muestra, así que no hay que escribirlas por duplicado.
+y la copia de escucha, así que no hay que escribirlas por duplicado.
El directorio privado se configura con `MEDIA_DIR`. Los detalles de formato, la
convención de nombres y cómo sustituir los archivos de marcador de posición
@@ -500,16 +504,17 @@ están en [`media/LEEME.md`](media/LEEME.md).
### Subir un tema sin tocar el disco
El campo **Archivo de audio** del panel sube el máster a `media/audio/subidas/`.
-Lo que el navegador no puede hacer —recortar la muestra y medir la duración— lo
+Lo que el navegador no puede hacer —transcodificar la escucha y medir el audio— lo
hace [`scripts/medios.mjs`](scripts/medios.mjs), que corre solo antes de
`npm run dev` y de `npm run build`, y también a mano con `npm run medios`:
coloca el archivo en la carpeta de su disco con el nombre de la convención,
-reescribe la clave en el Markdown, genera el fragmento y rellena `duracion` si
+reescribe la clave en el Markdown, genera la canción completa a 96 kbps y rellena `duracion` si
estaba vacía.
Necesita **ffmpeg** en el equipo de quien edita. Si falta, avisa de lo que no ha
podido generar y sigue; no rompe el arranque ni el build. El servidor de
-despliegue no lo necesita: las muestras están en el repositorio.
+despliegue no lo necesita: los derivados están en el repositorio. El perfil se
+define una sola vez en `scripts/config/audio.mjs`.
Un archivo que se quede en `subidas/` sin ficha que lo reclame se avisa en cada
arranque, para que no se pierda ahí.
@@ -807,8 +812,8 @@ música sigue sonando mientras se recorre la web. Su estado es una única
instancia de módulo ([`src/lib/player/player.svelte.ts`](src/lib/player/player.svelte.ts)),
no un contexto de Svelte, precisamente por eso.
-**Lo que suena siempre es el fragmento de muestra**, y la barra lo dice. El
-archivo completo solo se obtiene comprando.
+**Lo que suena es la canción completa en calidad de escucha.** La compra entrega
+la representación privada de mayor calidad e incluye las versiones musicales.
Qué hace: cola con orden propio, aleatorio (respetando el tema en curso),
repetición de cola o de tema, búsqueda dentro del tema, volumen recordado entre
@@ -920,9 +925,9 @@ Quien tiene cuenta puede puntuar un tema de 1 a 5 desde su ficha. La media y el
número de votos se ven siempre, también sin entrar: saber cómo está valorado un
tema no exige cuenta; lo que la exige es votar, para que un voto sea de alguien.
-**No hace falta haber comprado el tema.** Lo que suena en la web es un fragmento,
-y opinar sobre lo que se ha escuchado es el uso normal; exigir la compra
-convertiría la valoración en una reseña de producto.
+**No hace falta haber comprado el tema.** La web permite escucharlo completo en
+calidad reducida, y opinar sobre lo que se ha escuchado es el uso normal; exigir
+la compra convertiría la valoración en una reseña de producto.
Un voto por cuenta y tema, y volver a votar reemplaza el anterior. Eso lo impone
la **clave primaria compuesta** de la tabla `valoracion`, no el código de la
@@ -1037,16 +1042,17 @@ npm run test:unit -- --run
npm run test:e2e
```
-## El contenido se va a PostgreSQL
+## El contenido en PostgreSQL
Lo que hay hoy en `src/content/**` son registros disfrazados de documento, y eso
tiene un coste concreto: cinco tablas apuntan a una canción por una cadena de
texto sin clave foránea, así que **renombrar el slug de un tema deja huérfana una
compra sin que salte ningún error**.
-El modelo completo —41 tablas, con el porqué de cada decisión— está en
-[`docs/modelo-de-datos.md`](docs/modelo-de-datos.md). Está entregado y pendiente
-de verificación; no hay código escrito todavía.
+El modelo completo, con el porqué de cada decisión, está en
+[`docs/modelo-de-datos.md`](docs/modelo-de-datos.md). Las migraciones, el panel
+y las lecturas públicas ya están implementados; los volcamientos totales quedan
+reservados para bases sin actividad comercial.
## Despliegue
diff --git a/despliegue/senzapaura.nginx.conf b/despliegue/senzapaura.nginx.conf
index 1669673..fd75f55 100644
--- a/despliegue/senzapaura.nginx.conf
+++ b/despliegue/senzapaura.nginx.conf
@@ -53,7 +53,7 @@ server {
# mientras el DNS no haya propagado del todo.
server_name senzapaura.es www.senzapaura.es _;
- # Los mp3 completos pesan varios megas; los fragmentos, cientos de kilos.
+ # Los MP3 de escucha completa pesan varios megas.
client_max_body_size 20m;
gzip on;
@@ -79,7 +79,19 @@ server {
try_files $uri =404;
}
- # Imágenes, fuentes, vídeo, los fragmentos de muestra y el panel. No llevan
+ # El audio de escucha es público y completo, pero de calidad reducida. Nginx
+ # lo entrega directamente y anuncia rangos para que el reproductor pueda
+ # buscar dentro de la pista sin descargarla de nuevo desde el principio.
+ location /escucha/ {
+ root /var/www/senzapaura/build/client;
+ access_log off;
+ expires 1d;
+ add_header Cache-Control "public";
+ add_header Accept-Ranges "bytes" always;
+ try_files $uri =404;
+ }
+
+ # Imágenes, fuentes, vídeo, las muestras antiguas y el panel. No llevan
# huella, así que se cachean un día: lo justo para no pedirlos en cada
# visita sin que un cambio tarde una semana en verse.
location ~* ^/(images|background|video|muestras|fuentes|admin)/ {
@@ -95,9 +107,9 @@ server {
#
# Incluidas /descargas/… —que comprueban la compra antes de entregar el
# archivo—, la vuelta de Google y Facebook, y el webhook de Stripe. Ojo:
- # las descargas NO se pueden servir desde Nginx; el audio completo vive
- # fuera de `build/` justamente para que no haya forma de pedirlo por URL
- # sin haberlo comprado.
+ # las descargas NO se pueden servir desde Nginx; el audio original o de alta
+ # calidad vive fuera de `build/` justamente para que no haya forma de
+ # pedirlo por URL sin haberlo comprado.
# -----------------------------------------------------------------------
location / {
proxy_pass http://127.0.0.1:3000;
diff --git a/docs/modelo-de-datos.md b/docs/modelo-de-datos.md
index cd986c6..4bd3360 100644
--- a/docs/modelo-de-datos.md
+++ b/docs/modelo-de-datos.md
@@ -1,14 +1,14 @@
# Modelo de datos
-Diseño de la migración del contenido a PostgreSQL. **Fase 1 cerrada**: el
-modelo está completo y las decisiones tomadas. No hay código escrito todavía.
+Diseño y estado de la migración del contenido a PostgreSQL. El modelo base y
+el dominio musical están implementados en `src/lib/server/db/schema` y en las
+migraciones `0000`–`0014`.
Versión presentable, con diagramas entidad-relación:
-Este archivo es la especificación; el artefacto es la misma información puesta
-para leerse. Cuando se implemente, la verdad pasa a ser
-`src/lib/server/db/schema.ts` y esto queda como el porqué.
+Este archivo conserva el porqué; la verdad ejecutable es
+`src/lib/server/db/schema`.
## Por qué
@@ -100,8 +100,14 @@ que hoy leen `$lib/content`.
además lo correcto: la maqueta de 2018 no tiene la misma letra, le falta el
puente.
-- **`persona`** _(nueva)_ — nombre, nombre_legal, ipi. Hoy autores e intérpretes
- son cadenas sueltas repetidas en cada archivo.
+- **`persona`** — identidad física/legal para autoría, IPI y datos personales.
+- **`artista`** — identidad pública con código estable, slug, tipo
+ (persona/grupo/proyecto), descripción, biografía, imagen, país y estado.
+- **`artista_persona`** — vínculo opcional entre una identidad pública y las
+ personas físicas que la encarnan o integran.
+- **`artista_identificador`** — identificadores externos por sistema.
+- **`cancion_interprete`** — crédito de una grabación concreta a un artista,
+ con rol, instrumento, nombre acreditado y orden.
- **`cancion_persona`** _(nueva)_ — rol (letra · musica · interprete · arreglos ·
produccion), orden.
- ~~**`version`**~~ — **desaparece como tabla**: cada versión es una fila de
@@ -415,8 +421,8 @@ subrayado.
### 6 · Medios
-- **`medio`** _(nueva)_ — clase, clave, **`publico`** (los fragmentos sí, el
- audio completo nunca; hoy eso lo garantiza la carpeta), mime, bytes,
+- **`medio`** — clase, clave, **`publico`** (la copia completa de escucha sí;
+ másteres y descargas no), mime, bytes,
duracion_s, ancho, alto, sha256, alt. Para que la administración pueda subir
audio, un archivo tiene que ser una fila.
@@ -430,7 +436,7 @@ no hay que tocar ninguna URL —la base del dominio es configuración, y
descargas no usan URLs firmadas «porque el servidor ya tiene la sesión delante».
En otro dominio la sesión **ya no va delante**: esa es justo la gracia. Así que:
-- **Lo público** —portadas, muestras— se sirve directo y cacheado.
+- **Lo público** —portadas y copias completas de escucha— se sirve directo y cacheado.
- **El audio completo** pasa a necesitar **URL firmada con caducidad corta**: la
firma la pone la aplicación después de comprobar la compra, y Nginx la valida
con `secure_link`. Sin eso, el dominio de medios sería una puerta abierta al
diff --git a/docs/plan-implementacion-dominio-musical.md b/docs/plan-implementacion-dominio-musical.md
index dd137dc..b1d9c6a 100644
--- a/docs/plan-implementacion-dominio-musical.md
+++ b/docs/plan-implementacion-dominio-musical.md
@@ -11,6 +11,12 @@ principal y sus versiones musicales, pero dejará de confundir:
- un intérprete y su ficha pública;
- una representación técnica de audio para escucha, descarga o archivo.
+> Estado a 10 de septiembre de 2026: implementadas las guardas, transacciones,
+> migraciones aditivas, read models, fichas públicas, panel, pipeline de audio y
+> nueva versión de las condiciones de uso. La activación en una base compartida
+> requiere ejecutar `db:migrate` y después `db:medios`; las migraciones se han
+> ensayado dentro de una transacción revertida.
+
El trabajo será incremental. Las migraciones serán aditivas hasta que las
lecturas nuevas estén verificadas; ninguna columna ni relación actual se
retirará en la misma entrega que introduce su sustituta.
diff --git a/drizzle/0014_artistas_y_audio.sql b/drizzle/0014_artistas_y_audio.sql
index d44519f..ff2196d 100644
--- a/drizzle/0014_artistas_y_audio.sql
+++ b/drizzle/0014_artistas_y_audio.sql
@@ -201,3 +201,18 @@ INNER JOIN persona p ON p.id = cp.persona_id
INNER JOIN artista a ON a.slug = p.slug
WHERE cp.rol = 'interprete'
ON CONFLICT DO NOTHING;
+--> statement-breakpoint
+
+-- El legado solo acreditaba la principal. Una versión empieza heredando una
+-- copia de esos créditos, que después puede editarse de forma independiente.
+INSERT INTO cancion_interprete (
+ cancion_id, artista_id, rol, instrumento, acreditado_como, orden
+)
+SELECT v.id, ci.artista_id, ci.rol, ci.instrumento, ci.acreditado_como, ci.orden
+FROM cancion v
+INNER JOIN cancion_interprete ci ON ci.cancion_id = v.version_de_id
+WHERE v.version_de_id IS NOT NULL
+ AND NOT EXISTS (
+ SELECT 1 FROM cancion_interprete propia WHERE propia.cancion_id = v.id
+ )
+ON CONFLICT DO NOTHING;
diff --git a/drizzle/0015_condiciones_escucha_completa.sql b/drizzle/0015_condiciones_escucha_completa.sql
new file mode 100644
index 0000000..1002742
--- /dev/null
+++ b/drizzle/0015_condiciones_escucha_completa.sql
@@ -0,0 +1,84 @@
+-- Publica una versión nueva de las condiciones: las versiones legales ya
+-- vigentes no se modifican porque documentan lo aceptado en compras anteriores.
+INSERT INTO version_legal (
+ id, documento_id, cuerpo, vigente_desde, resumen_cambios
+)
+SELECT
+ 'legal-condiciones-uso-2026-09-10',
+ d.id,
+ $condiciones$
+> **Pendiente de revisión legal.** Es un borrador razonable, no un documento
+> validado por un abogado.
+
+Usar esta web supone aceptar estas condiciones. Si no estás de acuerdo con
+alguna, no la uses.
+
+## La cuenta
+
+Para comprar hace falta una cuenta, y para crearla basta un correo electrónico
+al que llega un código. **No hay contraseña**: cada vez que entras se envía un
+código nuevo. Eso significa que quien tenga acceso a tu correo tiene acceso a
+tu cuenta, así que protégelo.
+
+Al crear la cuenta te comprometes a usar una dirección **tuya**. Escribir la de
+otra persona para que le lleguen los códigos es un uso indebido, y el sistema
+lo limita activamente.
+
+Puedes pedir que se cierre tu cuenta cuando quieras escribiendo a
+hola@senzapaura.es. Las compras y los datos de facturación se conservan el
+tiempo que obliga la ley, según se explica en la
+[política de privacidad](/legal/privacidad).
+
+## Lo que suena y lo que se compra
+
+En la web se puede escuchar **la canción completa en una copia de calidad
+reducida**. Esa copia es solo para escucharla desde el sitio: que sea accesible
+no concede permiso para descargarla, redistribuirla ni reutilizarla.
+
+Al comprar recibes el archivo de mayor calidad disponible, con todas sus
+versiones alternativas, y queda vinculado a tu cuenta: puedes volver a
+descargarlo desde ella siempre que quieras.
+
+## Lo que no se puede hacer
+
+Con las canciones compradas:
+
+- Redistribuirlas, subirlas a ninguna plataforma ni compartirlas públicamente.
+- Usarlas en vídeos, anuncios, espectáculos o cualquier producción.
+- Incorporarlas a otra obra o hacer versiones para explotarlas.
+
+Todo eso requiere una licencia aparte. Los identificadores de registro están en
+la ficha de cada tema para poder pedirla.
+
+Con la web:
+
+- Intentar acceder a partes que no te corresponden, o a los archivos originales
+ o de descarga sin haberlos comprado.
+- Automatizar peticiones de forma que degraden el servicio.
+- Usar el formulario de acceso o el de contacto para molestar a terceros.
+
+## El taller de letras
+
+Los textos del taller se publican para leerlos y aprender. Puedes usarlos para
+escribir tus propias canciones —para eso están— pero no republicarlos como
+propios ni venderlos.
+
+## Cambios
+
+Estas condiciones pueden cambiar. La fecha de arriba dice cuándo se revisaron
+por última vez, y lo que se aplica a una compra son las condiciones vigentes en
+el momento de hacerla.
+$condiciones$,
+ TIMESTAMPTZ '2026-09-10 00:00:00+02',
+ 'La escucha pública pasa de un fragmento a la canción completa en calidad reducida.'
+FROM documento_legal d
+WHERE d.slug = 'condiciones-de-uso'
+ON CONFLICT (id) DO NOTHING;
+--> statement-breakpoint
+
+UPDATE documento_legal d
+SET version_vigente_id = v.id
+FROM version_legal v
+WHERE d.slug = 'condiciones-de-uso'
+ AND v.id = 'legal-condiciones-uso-2026-09-10'
+ AND v.documento_id = d.id;
diff --git a/drizzle/0016_sincronizar_migraciones_manuales.sql b/drizzle/0016_sincronizar_migraciones_manuales.sql
new file mode 100644
index 0000000..060cee1
--- /dev/null
+++ b/drizzle/0016_sincronizar_migraciones_manuales.sql
@@ -0,0 +1,2 @@
+-- Sin cambios SQL. Punto de enlace creado por Drizzle antes de reconciliar las
+-- migraciones manuales 0011–0015 con el esquema declarado.
diff --git a/drizzle/0017_verificar_sincronizacion.sql b/drizzle/0017_verificar_sincronizacion.sql
new file mode 100644
index 0000000..69b8da4
--- /dev/null
+++ b/drizzle/0017_verificar_sincronizacion.sql
@@ -0,0 +1,3 @@
+-- Sin cambios SQL. La instantánea asociada representa el esquema resultante de
+-- 0011–0015; esas operaciones ya viven en sus migraciones manuales y repetirlas
+-- aquí intentaría crear de nuevo las mismas tablas, columnas e índices.
diff --git a/drizzle/meta/0016_snapshot.json b/drizzle/meta/0016_snapshot.json
new file mode 100644
index 0000000..b7fc9ad
--- /dev/null
+++ b/drizzle/meta/0016_snapshot.json
@@ -0,0 +1,6149 @@
+{
+ "id": "89cab2aa-355f-45b2-ace8-7afc914b9b6d",
+ "prevId": "30625049-98ca-4735-bee2-28f9bd917f7a",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.medio": {
+ "name": "medio",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "clase": {
+ "name": "clase",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "publico": {
+ "name": "publico",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "mime": {
+ "name": "mime",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bytes": {
+ "name": "bytes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "duracion_s": {
+ "name": "duracion_s",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ancho": {
+ "name": "ancho",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "alto": {
+ "name": "alto",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sha256": {
+ "name": "sha256",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "alt": {
+ "name": "alt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "medio_clase": {
+ "name": "medio_clase",
+ "columns": [
+ {
+ "expression": "clase",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "medio_sha": {
+ "name": "medio_sha",
+ "columns": [
+ {
+ "expression": "sha256",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "medio_clave_unique": {
+ "name": "medio_clave_unique",
+ "columns": [
+ "clave"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pais": {
+ "name": "pais",
+ "schema": "",
+ "columns": {
+ "codigo": {
+ "name": "codigo",
+ "type": "char(2)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "gentilicio": {
+ "name": "gentilicio",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "region": {
+ "name": "region",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.persona": {
+ "name": "persona",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre_legal": {
+ "name": "nombre_legal",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ipi": {
+ "name": "ipi",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nacimiento": {
+ "name": "nacimiento",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "defuncion": {
+ "name": "defuncion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retrato_id": {
+ "name": "retrato_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "semblanza": {
+ "name": "semblanza",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "persona_nombre": {
+ "name": "persona_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "persona_pais": {
+ "name": "persona_pais",
+ "columns": [
+ {
+ "expression": "pais_codigo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "persona_pais_codigo_pais_codigo_fk": {
+ "name": "persona_pais_codigo_pais_codigo_fk",
+ "tableFrom": "persona",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "persona_retrato_id_medio_id_fk": {
+ "name": "persona_retrato_id_medio_id_fk",
+ "tableFrom": "persona",
+ "columnsFrom": [
+ "retrato_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "persona_slug_unique": {
+ "name": "persona_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.album": {
+ "name": "album",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estilo_id": {
+ "name": "estilo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'album'"
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "portada_id": {
+ "name": "portada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sello": {
+ "name": "sello",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "destacado": {
+ "name": "destacado",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "numero_catalogo": {
+ "name": "numero_catalogo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "formatos": {
+ "name": "formatos",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_edicion_codigo": {
+ "name": "pais_edicion_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "album_estilo": {
+ "name": "album_estilo",
+ "columns": [
+ {
+ "expression": "estilo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "album_fecha": {
+ "name": "album_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "album_estilo_id_estilo_id_fk": {
+ "name": "album_estilo_id_estilo_id_fk",
+ "tableFrom": "album",
+ "columnsFrom": [
+ "estilo_id"
+ ],
+ "tableTo": "estilo",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "album_portada_id_medio_id_fk": {
+ "name": "album_portada_id_medio_id_fk",
+ "tableFrom": "album",
+ "columnsFrom": [
+ "portada_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "album_pais_edicion_codigo_pais_codigo_fk": {
+ "name": "album_pais_edicion_codigo_pais_codigo_fk",
+ "tableFrom": "album",
+ "columnsFrom": [
+ "pais_edicion_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "album_slug_unique": {
+ "name": "album_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.album_enlace": {
+ "name": "album_enlace",
+ "schema": "",
+ "columns": {
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "album_enlace_album_id_album_id_fk": {
+ "name": "album_enlace_album_id_album_id_fk",
+ "tableFrom": "album_enlace",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "tableTo": "album",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "album_enlace_album_id_plataforma_pk": {
+ "name": "album_enlace_album_id_plataforma_pk",
+ "columns": [
+ "album_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.autoria": {
+ "name": "autoria",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "porcentaje": {
+ "name": "porcentaje",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "autoria_cancion_id_cancion_id_fk": {
+ "name": "autoria_cancion_id_cancion_id_fk",
+ "tableFrom": "autoria",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "autoria_persona_id_persona_id_fk": {
+ "name": "autoria_persona_id_persona_id_fk",
+ "tableFrom": "autoria",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "tableTo": "persona",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "autoria_cancion_id_persona_id_rol_pk": {
+ "name": "autoria_cancion_id_persona_id_rol_pk",
+ "columns": [
+ "cancion_id",
+ "persona_id",
+ "rol"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion": {
+ "name": "cancion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "version_de_id": {
+ "name": "version_de_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_nombre": {
+ "name": "version_nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_nota": {
+ "name": "version_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_orden": {
+ "name": "version_orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "estilo_id": {
+ "name": "estilo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "audio_id": {
+ "name": "audio_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "muestra_id": {
+ "name": "muestra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "duracion_s": {
+ "name": "duracion_s",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ano": {
+ "name": "ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "letra": {
+ "name": "letra",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'es'"
+ },
+ "inspiracion": {
+ "name": "inspiracion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "instrumental": {
+ "name": "instrumental",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "destacada": {
+ "name": "destacada",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "portada_id": {
+ "name": "portada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ala_venta": {
+ "name": "ala_venta",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "cancion_estilo": {
+ "name": "cancion_estilo",
+ "columns": [
+ {
+ "expression": "estilo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "cancion_album": {
+ "name": "cancion_album",
+ "columns": [
+ {
+ "expression": "album_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "cancion_version_de": {
+ "name": "cancion_version_de",
+ "columns": [
+ {
+ "expression": "version_de_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "cancion_destacada": {
+ "name": "cancion_destacada",
+ "columns": [
+ {
+ "expression": "destacada",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "cancion_estilo_id_estilo_id_fk": {
+ "name": "cancion_estilo_id_estilo_id_fk",
+ "tableFrom": "cancion",
+ "columnsFrom": [
+ "estilo_id"
+ ],
+ "tableTo": "estilo",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "cancion_album_id_album_id_fk": {
+ "name": "cancion_album_id_album_id_fk",
+ "tableFrom": "cancion",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "tableTo": "album",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "cancion_audio_id_medio_id_fk": {
+ "name": "cancion_audio_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "columnsFrom": [
+ "audio_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "cancion_muestra_id_medio_id_fk": {
+ "name": "cancion_muestra_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "columnsFrom": [
+ "muestra_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "cancion_portada_id_medio_id_fk": {
+ "name": "cancion_portada_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "columnsFrom": [
+ "portada_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cancion_slug_unique": {
+ "name": "cancion_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_enlace": {
+ "name": "cancion_enlace",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_enlace_cancion_id_cancion_id_fk": {
+ "name": "cancion_enlace_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_enlace",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_enlace_cancion_id_plataforma_pk": {
+ "name": "cancion_enlace_cancion_id_plataforma_pk",
+ "columns": [
+ "cancion_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_etiqueta": {
+ "name": "cancion_etiqueta",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_etiqueta_cancion_id_cancion_id_fk": {
+ "name": "cancion_etiqueta_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_etiqueta",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "cancion_etiqueta_etiqueta_id_etiqueta_id_fk": {
+ "name": "cancion_etiqueta_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "cancion_etiqueta",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "tableTo": "etiqueta",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_etiqueta_cancion_id_etiqueta_id_pk": {
+ "name": "cancion_etiqueta_cancion_id_etiqueta_id_pk",
+ "columns": [
+ "cancion_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_persona": {
+ "name": "cancion_persona",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_persona_cancion_id_cancion_id_fk": {
+ "name": "cancion_persona_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_persona",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "cancion_persona_persona_id_persona_id_fk": {
+ "name": "cancion_persona_persona_id_persona_id_fk",
+ "tableFrom": "cancion_persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "tableTo": "persona",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_persona_cancion_id_persona_id_rol_pk": {
+ "name": "cancion_persona_cancion_id_persona_id_rol_pk",
+ "columns": [
+ "cancion_id",
+ "persona_id",
+ "rol"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.credito_album": {
+ "name": "credito_album",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "credito_album_album": {
+ "name": "credito_album_album",
+ "columns": [
+ {
+ "expression": "album_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "credito_album_album_id_album_id_fk": {
+ "name": "credito_album_album_id_album_id_fk",
+ "tableFrom": "credito_album",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "tableTo": "album",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "credito_album_persona_id_persona_id_fk": {
+ "name": "credito_album_persona_id_persona_id_fk",
+ "tableFrom": "credito_album",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "tableTo": "persona",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.estilo": {
+ "name": "estilo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "estilo_principal_unico": {
+ "name": "estilo_principal_unico",
+ "columns": [
+ {
+ "expression": "principal",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "with": {},
+ "method": "btree",
+ "where": "\"estilo\".\"principal\"",
+ "concurrently": false
+ },
+ "estilo_orden": {
+ "name": "estilo_orden",
+ "columns": [
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "estilo_imagen_id_medio_id_fk": {
+ "name": "estilo_imagen_id_medio_id_fk",
+ "tableFrom": "estilo",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "estilo_slug_unique": {
+ "name": "estilo_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.etiqueta": {
+ "name": "etiqueta",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "etiqueta_slug_unique": {
+ "name": "etiqueta_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.registro_obra": {
+ "name": "registro_obra",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "iswc": {
+ "name": "iswc",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "isrc": {
+ "name": "isrc",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "entidad": {
+ "name": "entidad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numero": {
+ "name": "numero",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "editorial": {
+ "name": "editorial",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "registro_obra_cancion_id_cancion_id_fk": {
+ "name": "registro_obra_cancion_id_cancion_id_fk",
+ "tableFrom": "registro_obra",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.traduccion": {
+ "name": "traduccion",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "texto": {
+ "name": "texto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "traduccion_cancion_id_cancion_id_fk": {
+ "name": "traduccion_cancion_id_cancion_id_fk",
+ "tableFrom": "traduccion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "traduccion_cancion_id_idioma_pk": {
+ "name": "traduccion_cancion_id_idioma_pk",
+ "columns": [
+ "cancion_id",
+ "idioma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.video": {
+ "name": "video",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "youtube_id": {
+ "name": "youtube_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "video_cancion": {
+ "name": "video_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "video_cancion_id_cancion_id_fk": {
+ "name": "video_cancion_id_cancion_id_fk",
+ "tableFrom": "video",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.acepcion": {
+ "name": "acepcion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "categoria": {
+ "name": "categoria",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "definicion": {
+ "name": "definicion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ampliacion": {
+ "name": "ampliacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ejemplo": {
+ "name": "ejemplo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "acepcion_numero": {
+ "name": "acepcion_numero",
+ "columns": [
+ {
+ "expression": "termino_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "numero",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "acepcion_termino_id_termino_id_fk": {
+ "name": "acepcion_termino_id_termino_id_fk",
+ "tableFrom": "acepcion",
+ "columnsFrom": [
+ "termino_id"
+ ],
+ "tableTo": "termino",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.animo": {
+ "name": "animo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "gems": {
+ "name": "gems",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valencia": {
+ "name": "valencia",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "energia": {
+ "name": "energia",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "animo_codigo_unique": {
+ "name": "animo_codigo_unique",
+ "columns": [
+ "codigo"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_genero": {
+ "name": "cancion_genero",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_genero_cancion_id_cancion_id_fk": {
+ "name": "cancion_genero_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_genero",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "cancion_genero_genero_id_genero_id_fk": {
+ "name": "cancion_genero_genero_id_genero_id_fk",
+ "tableFrom": "cancion_genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_genero_cancion_id_genero_id_pk": {
+ "name": "cancion_genero_cancion_id_genero_id_pk",
+ "columns": [
+ "cancion_id",
+ "genero_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.capitulo": {
+ "name": "capitulo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "capitulo_tipo": {
+ "name": "capitulo_tipo",
+ "columns": [
+ {
+ "expression": "tipo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "capitulo_genero_id_genero_id_fk": {
+ "name": "capitulo_genero_id_genero_id_fk",
+ "tableFrom": "capitulo",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "capitulo_slug_unique": {
+ "name": "capitulo_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.capitulo_acepcion": {
+ "name": "capitulo_acepcion",
+ "schema": "",
+ "columns": {
+ "capitulo_id": {
+ "name": "capitulo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "acepcion_id": {
+ "name": "acepcion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "automatico": {
+ "name": "automatico",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "confirmado": {
+ "name": "confirmado",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "capitulo_acepcion_capitulo_id_capitulo_id_fk": {
+ "name": "capitulo_acepcion_capitulo_id_capitulo_id_fk",
+ "tableFrom": "capitulo_acepcion",
+ "columnsFrom": [
+ "capitulo_id"
+ ],
+ "tableTo": "capitulo",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "capitulo_acepcion_acepcion_id_acepcion_id_fk": {
+ "name": "capitulo_acepcion_acepcion_id_acepcion_id_fk",
+ "tableFrom": "capitulo_acepcion",
+ "columnsFrom": [
+ "acepcion_id"
+ ],
+ "tableTo": "acepcion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "capitulo_acepcion_capitulo_id_acepcion_id_pk": {
+ "name": "capitulo_acepcion_capitulo_id_acepcion_id_pk",
+ "columns": [
+ "capitulo_id",
+ "acepcion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.compas": {
+ "name": "compas",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numerador": {
+ "name": "numerador",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "denominador": {
+ "name": "denominador",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "compas_codigo_unique": {
+ "name": "compas_codigo_unique",
+ "columns": [
+ "codigo"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero": {
+ "name": "genero",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "origen_lugar": {
+ "name": "origen_lugar",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "origen_ano": {
+ "name": "origen_ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tempo": {
+ "name": "tempo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metrica_nota": {
+ "name": "metrica_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "compas_nota": {
+ "name": "compas_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rasgos": {
+ "name": "rasgos",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "genero_nombre": {
+ "name": "genero_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "genero_origen_ano": {
+ "name": "genero_origen_ano",
+ "columns": [
+ {
+ "expression": "origen_ano",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "genero_slug_unique": {
+ "name": "genero_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_alias": {
+ "name": "genero_alias",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "genero_alias_nombre": {
+ "name": "genero_alias_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "genero_alias_genero_id_genero_id_fk": {
+ "name": "genero_alias_genero_id_genero_id_fk",
+ "tableFrom": "genero_alias",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_alias_pais_codigo_pais_codigo_fk": {
+ "name": "genero_alias_pais_codigo_pais_codigo_fk",
+ "tableFrom": "genero_alias",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_compas": {
+ "name": "genero_compas",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "compas_id": {
+ "name": "compas_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_compas_genero_id_genero_id_fk": {
+ "name": "genero_compas_genero_id_genero_id_fk",
+ "tableFrom": "genero_compas",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_compas_compas_id_compas_id_fk": {
+ "name": "genero_compas_compas_id_compas_id_fk",
+ "tableFrom": "genero_compas",
+ "columnsFrom": [
+ "compas_id"
+ ],
+ "tableTo": "compas",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_compas_genero_id_compas_id_pk": {
+ "name": "genero_compas_genero_id_compas_id_pk",
+ "columns": [
+ "genero_id",
+ "compas_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_instrumento": {
+ "name": "genero_instrumento",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "instrumento_id": {
+ "name": "instrumento_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "importancia": {
+ "name": "importancia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'habitual'"
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_instrumento_genero_id_genero_id_fk": {
+ "name": "genero_instrumento_genero_id_genero_id_fk",
+ "tableFrom": "genero_instrumento",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_instrumento_instrumento_id_instrumento_id_fk": {
+ "name": "genero_instrumento_instrumento_id_instrumento_id_fk",
+ "tableFrom": "genero_instrumento",
+ "columnsFrom": [
+ "instrumento_id"
+ ],
+ "tableTo": "instrumento",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_instrumento_genero_id_instrumento_id_pk": {
+ "name": "genero_instrumento_genero_id_instrumento_id_pk",
+ "columns": [
+ "genero_id",
+ "instrumento_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_metro": {
+ "name": "genero_metro",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metro_id": {
+ "name": "metro_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "predominante": {
+ "name": "predominante",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_metro_genero_id_genero_id_fk": {
+ "name": "genero_metro_genero_id_genero_id_fk",
+ "tableFrom": "genero_metro",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_metro_metro_id_metro_id_fk": {
+ "name": "genero_metro_metro_id_metro_id_fk",
+ "tableFrom": "genero_metro",
+ "columnsFrom": [
+ "metro_id"
+ ],
+ "tableTo": "metro",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_metro_genero_id_metro_id_pk": {
+ "name": "genero_metro_genero_id_metro_id_pk",
+ "columns": [
+ "genero_id",
+ "metro_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_origen": {
+ "name": "genero_origen",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "origen_id": {
+ "name": "origen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "genero_origen_origen": {
+ "name": "genero_origen_origen",
+ "columns": [
+ {
+ "expression": "origen_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "genero_origen_genero_id_genero_id_fk": {
+ "name": "genero_origen_genero_id_genero_id_fk",
+ "tableFrom": "genero_origen",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_origen_origen_id_genero_id_fk": {
+ "name": "genero_origen_origen_id_genero_id_fk",
+ "tableFrom": "genero_origen",
+ "columnsFrom": [
+ "origen_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_origen_genero_id_origen_id_tipo_pk": {
+ "name": "genero_origen_genero_id_origen_id_tipo_pk",
+ "columns": [
+ "genero_id",
+ "origen_id",
+ "tipo"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_pais": {
+ "name": "genero_pais",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "relacion": {
+ "name": "relacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'adoptado'"
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_pais_genero_id_genero_id_fk": {
+ "name": "genero_pais_genero_id_genero_id_fk",
+ "tableFrom": "genero_pais",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_pais_pais_codigo_pais_codigo_fk": {
+ "name": "genero_pais_pais_codigo_pais_codigo_fk",
+ "tableFrom": "genero_pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_pais_genero_id_pais_codigo_pk": {
+ "name": "genero_pais_genero_id_pais_codigo_pk",
+ "columns": [
+ "genero_id",
+ "pais_codigo"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_persona": {
+ "name": "genero_persona",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_persona_genero_id_genero_id_fk": {
+ "name": "genero_persona_genero_id_genero_id_fk",
+ "tableFrom": "genero_persona",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_persona_persona_id_persona_id_fk": {
+ "name": "genero_persona_persona_id_persona_id_fk",
+ "tableFrom": "genero_persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "tableTo": "persona",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_persona_genero_id_persona_id_papel_pk": {
+ "name": "genero_persona_genero_id_persona_id_papel_pk",
+ "columns": [
+ "genero_id",
+ "persona_id",
+ "papel"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_seccion": {
+ "name": "genero_seccion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "genero_seccion_clave": {
+ "name": "genero_seccion_clave",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "clave",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "genero_seccion_genero_id_genero_id_fk": {
+ "name": "genero_seccion_genero_id_genero_id_fk",
+ "tableFrom": "genero_seccion",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_tema": {
+ "name": "genero_tema",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_tema_genero_id_genero_id_fk": {
+ "name": "genero_tema_genero_id_genero_id_fk",
+ "tableFrom": "genero_tema",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "genero_tema_etiqueta_id_etiqueta_id_fk": {
+ "name": "genero_tema_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "genero_tema",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "tableTo": "etiqueta",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_tema_genero_id_etiqueta_id_pk": {
+ "name": "genero_tema_genero_id_etiqueta_id_pk",
+ "columns": [
+ "genero_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.instrumento": {
+ "name": "instrumento",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "familia": {
+ "name": "familia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "subfamilia": {
+ "name": "subfamilia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "afinacion": {
+ "name": "afinacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "muestra_id": {
+ "name": "muestra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "instrumento_familia": {
+ "name": "instrumento_familia",
+ "columns": [
+ {
+ "expression": "familia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "instrumento_pais_codigo_pais_codigo_fk": {
+ "name": "instrumento_pais_codigo_pais_codigo_fk",
+ "tableFrom": "instrumento",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "instrumento_imagen_id_medio_id_fk": {
+ "name": "instrumento_imagen_id_medio_id_fk",
+ "tableFrom": "instrumento",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "instrumento_muestra_id_medio_id_fk": {
+ "name": "instrumento_muestra_id_medio_id_fk",
+ "tableFrom": "instrumento",
+ "columnsFrom": [
+ "muestra_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "instrumento_slug_unique": {
+ "name": "instrumento_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.metro": {
+ "name": "metro",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "silabas": {
+ "name": "silabas",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "metro_codigo_unique": {
+ "name": "metro_codigo_unique",
+ "columns": [
+ "codigo"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.modelo_ia": {
+ "name": "modelo_ia",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "familia": {
+ "name": "familia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "version": {
+ "name": "version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vigente": {
+ "name": "vigente",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "nota_sintaxis": {
+ "name": "nota_sintaxis",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "esquema": {
+ "name": "esquema",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "modelo_ia_familia": {
+ "name": "modelo_ia_familia",
+ "columns": [
+ {
+ "expression": "familia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "modelo_ia_codigo_unique": {
+ "name": "modelo_ia_codigo_unique",
+ "columns": [
+ "codigo"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia": {
+ "name": "obra_referencia",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ano": {
+ "name": "ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cita": {
+ "name": "cita",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "obra_referencia_genero": {
+ "name": "obra_referencia_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "obra_referencia_genero_id_genero_id_fk": {
+ "name": "obra_referencia_genero_id_genero_id_fk",
+ "tableFrom": "obra_referencia",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "obra_referencia_slug_unique": {
+ "name": "obra_referencia_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia_enlace": {
+ "name": "obra_referencia_enlace",
+ "schema": "",
+ "columns": {
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "obra_referencia_enlace_obra_id_obra_referencia_id_fk": {
+ "name": "obra_referencia_enlace_obra_id_obra_referencia_id_fk",
+ "tableFrom": "obra_referencia_enlace",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "tableTo": "obra_referencia",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "obra_referencia_enlace_obra_id_plataforma_pk": {
+ "name": "obra_referencia_enlace_obra_id_plataforma_pk",
+ "columns": [
+ "obra_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia_persona": {
+ "name": "obra_referencia_persona",
+ "schema": "",
+ "columns": {
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "obra_referencia_persona_obra_id_obra_referencia_id_fk": {
+ "name": "obra_referencia_persona_obra_id_obra_referencia_id_fk",
+ "tableFrom": "obra_referencia_persona",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "tableTo": "obra_referencia",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "obra_referencia_persona_persona_id_persona_id_fk": {
+ "name": "obra_referencia_persona_persona_id_persona_id_fk",
+ "tableFrom": "obra_referencia_persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "tableTo": "persona",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "obra_referencia_persona_obra_id_persona_id_papel_pk": {
+ "name": "obra_referencia_persona_obra_id_persona_id_papel_pk",
+ "columns": [
+ "obra_id",
+ "persona_id",
+ "papel"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.prompt": {
+ "name": "prompt",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "modelo_ia_id": {
+ "name": "modelo_ia_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "animo_id": {
+ "name": "animo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'en'"
+ },
+ "contenido": {
+ "name": "contenido",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "notas": {
+ "name": "notas",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valoracion": {
+ "name": "valoracion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ejemplo_id": {
+ "name": "ejemplo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "preferido": {
+ "name": "preferido",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "visibilidad": {
+ "name": "visibilidad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'privado'"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "prompt_genero": {
+ "name": "prompt_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "prompt_modelo": {
+ "name": "prompt_modelo",
+ "columns": [
+ {
+ "expression": "modelo_ia_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "prompt_animo": {
+ "name": "prompt_animo",
+ "columns": [
+ {
+ "expression": "animo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "prompt_modelo_ia_id_modelo_ia_id_fk": {
+ "name": "prompt_modelo_ia_id_modelo_ia_id_fk",
+ "tableFrom": "prompt",
+ "columnsFrom": [
+ "modelo_ia_id"
+ ],
+ "tableTo": "modelo_ia",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "prompt_genero_id_genero_id_fk": {
+ "name": "prompt_genero_id_genero_id_fk",
+ "tableFrom": "prompt",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "prompt_animo_id_animo_id_fk": {
+ "name": "prompt_animo_id_animo_id_fk",
+ "tableFrom": "prompt",
+ "columnsFrom": [
+ "animo_id"
+ ],
+ "tableTo": "animo",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "prompt_ejemplo_id_medio_id_fk": {
+ "name": "prompt_ejemplo_id_medio_id_fk",
+ "tableFrom": "prompt",
+ "columnsFrom": [
+ "ejemplo_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.termino": {
+ "name": "termino",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "termino": {
+ "name": "termino",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "termino_slug_unique": {
+ "name": "termino_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ },
+ "termino_termino_unique": {
+ "name": "termino_termino_unique",
+ "columns": [
+ "termino"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.termino_variante": {
+ "name": "termino_variante",
+ "schema": "",
+ "columns": {
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "forma": {
+ "name": "forma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "termino_variante_termino_id_termino_id_fk": {
+ "name": "termino_variante_termino_id_termino_id_fk",
+ "tableFrom": "termino_variante",
+ "columnsFrom": [
+ "termino_id"
+ ],
+ "tableTo": "termino",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "termino_variante_termino_id_forma_pk": {
+ "name": "termino_variante_termino_id_forma_pk",
+ "columns": [
+ "termino_id",
+ "forma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.verso": {
+ "name": "verso",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ilustra": {
+ "name": "ilustra",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "fuente": {
+ "name": "fuente",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'ejemplo'"
+ },
+ "analisis": {
+ "name": "analisis",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "medida": {
+ "name": "medida",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "verso_genero": {
+ "name": "verso_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "verso_genero_id_genero_id_fk": {
+ "name": "verso_genero_id_genero_id_fk",
+ "tableFrom": "verso",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "tableTo": "genero",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "verso_obra_id_obra_referencia_id_fk": {
+ "name": "verso_obra_id_obra_referencia_id_fk",
+ "tableFrom": "verso",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "tableTo": "obra_referencia",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ },
+ "verso_cancion_id_cancion_id_fk": {
+ "name": "verso_cancion_id_cancion_id_fk",
+ "tableFrom": "verso",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.verso_linea": {
+ "name": "verso_linea",
+ "schema": "",
+ "columns": {
+ "verso_id": {
+ "name": "verso_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "texto": {
+ "name": "texto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "silabas": {
+ "name": "silabas",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tonicas": {
+ "name": "tonicas",
+ "type": "integer[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "medida": {
+ "name": "medida",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "verso_linea_verso_id_verso_id_fk": {
+ "name": "verso_linea_verso_id_verso_id_fk",
+ "tableFrom": "verso_linea",
+ "columnsFrom": [
+ "verso_id"
+ ],
+ "tableTo": "verso",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "verso_linea_verso_id_numero_pk": {
+ "name": "verso_linea_verso_id_numero_pk",
+ "columns": [
+ "verso_id",
+ "numero"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.documento_legal": {
+ "name": "documento_legal",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "version_vigente_id": {
+ "name": "version_vigente_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "documento_legal_slug_unique": {
+ "name": "documento_legal_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada": {
+ "name": "entrada",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "entrada_fecha": {
+ "name": "entrada_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "entrada_imagen_id_medio_id_fk": {
+ "name": "entrada_imagen_id_medio_id_fk",
+ "tableFrom": "entrada",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "tableTo": "medio",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "entrada_slug_unique": {
+ "name": "entrada_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada_cancion": {
+ "name": "entrada_cancion",
+ "schema": "",
+ "columns": {
+ "entrada_id": {
+ "name": "entrada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "entrada_cancion_entrada_id_entrada_id_fk": {
+ "name": "entrada_cancion_entrada_id_entrada_id_fk",
+ "tableFrom": "entrada_cancion",
+ "columnsFrom": [
+ "entrada_id"
+ ],
+ "tableTo": "entrada",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "entrada_cancion_cancion_id_cancion_id_fk": {
+ "name": "entrada_cancion_cancion_id_cancion_id_fk",
+ "tableFrom": "entrada_cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "entrada_cancion_entrada_id_cancion_id_pk": {
+ "name": "entrada_cancion_entrada_id_cancion_id_pk",
+ "columns": [
+ "entrada_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada_etiqueta": {
+ "name": "entrada_etiqueta",
+ "schema": "",
+ "columns": {
+ "entrada_id": {
+ "name": "entrada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "entrada_etiqueta_entrada_id_entrada_id_fk": {
+ "name": "entrada_etiqueta_entrada_id_entrada_id_fk",
+ "tableFrom": "entrada_etiqueta",
+ "columnsFrom": [
+ "entrada_id"
+ ],
+ "tableTo": "entrada",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "entrada_etiqueta_etiqueta_id_etiqueta_id_fk": {
+ "name": "entrada_etiqueta_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "entrada_etiqueta",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "tableTo": "etiqueta",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "entrada_etiqueta_entrada_id_etiqueta_id_pk": {
+ "name": "entrada_etiqueta_entrada_id_etiqueta_id_pk",
+ "columns": [
+ "entrada_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pagina": {
+ "name": "pagina",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "pagina_slug_unique": {
+ "name": "pagina_slug_unique",
+ "columns": [
+ "slug"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.redireccion": {
+ "name": "redireccion",
+ "schema": "",
+ "columns": {
+ "desde": {
+ "name": "desde",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "hacia": {
+ "name": "hacia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "permanente": {
+ "name": "permanente",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "motivo": {
+ "name": "motivo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "redireccion_hacia": {
+ "name": "redireccion_hacia",
+ "columns": [
+ {
+ "expression": "hacia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.version_legal": {
+ "name": "version_legal",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "documento_id": {
+ "name": "documento_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vigente_desde": {
+ "name": "vigente_desde",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "resumen_cambios": {
+ "name": "resumen_cambios",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "version_legal_documento": {
+ "name": "version_legal_documento",
+ "columns": [
+ {
+ "expression": "documento_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "vigente_desde",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "version_legal_documento_id_documento_legal_id_fk": {
+ "name": "version_legal_documento_id_documento_legal_id_fk",
+ "tableFrom": "version_legal",
+ "columnsFrom": [
+ "documento_id"
+ ],
+ "tableTo": "documento_legal",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.contador_factura": {
+ "name": "contador_factura",
+ "schema": "",
+ "columns": {
+ "serie": {
+ "name": "serie",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "ultimo_numero": {
+ "name": "ultimo_numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.datos_facturacion": {
+ "name": "datos_facturacion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'particular'"
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nif": {
+ "name": "nif",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "direccion": {
+ "name": "direccion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cp": {
+ "name": "cp",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ciudad": {
+ "name": "ciudad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "provincia": {
+ "name": "provincia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "predeterminada": {
+ "name": "predeterminada",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "datos_facturacion_usuario": {
+ "name": "datos_facturacion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "datos_facturacion_usuario_id_usuario_id_fk": {
+ "name": "datos_facturacion_usuario_id_usuario_id_fk",
+ "tableFrom": "datos_facturacion",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "datos_facturacion_pais_codigo_pais_codigo_fk": {
+ "name": "datos_facturacion_pais_codigo_pais_codigo_fk",
+ "tableFrom": "datos_facturacion",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.descarga": {
+ "name": "descarga",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bajada_en": {
+ "name": "bajada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ip": {
+ "name": "ip",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "agente": {
+ "name": "agente",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "descarga_usuario": {
+ "name": "descarga_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "descarga_fecha": {
+ "name": "descarga_fecha",
+ "columns": [
+ {
+ "expression": "bajada_en",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "descarga_usuario_id_usuario_id_fk": {
+ "name": "descarga_usuario_id_usuario_id_fk",
+ "tableFrom": "descarga",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "descarga_cancion_id_cancion_id_fk": {
+ "name": "descarga_cancion_id_cancion_id_fk",
+ "tableFrom": "descarga",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "restrict"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.factura": {
+ "name": "factura",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "serie": {
+ "name": "serie",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'normal'"
+ },
+ "rectifica_a_id": {
+ "name": "rectifica_a_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "base_centimos": {
+ "name": "base_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "iva_tipo": {
+ "name": "iva_tipo",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "iva_cuota_centimos": {
+ "name": "iva_cuota_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_centimos": {
+ "name": "total_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "moneda": {
+ "name": "moneda",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'eur'"
+ },
+ "datos_congelados": {
+ "name": "datos_congelados",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "factura_serie_numero": {
+ "name": "factura_serie_numero",
+ "columns": [
+ {
+ "expression": "serie",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "numero",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "factura_pedido": {
+ "name": "factura_pedido",
+ "columns": [
+ {
+ "expression": "pedido_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "factura_fecha": {
+ "name": "factura_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "factura_pedido_id_pedido_id_fk": {
+ "name": "factura_pedido_id_pedido_id_fk",
+ "tableFrom": "factura",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "tableTo": "pedido",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ },
+ "factura_pais_codigo_pais_codigo_fk": {
+ "name": "factura_pais_codigo_pais_codigo_fk",
+ "tableFrom": "factura",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "tableTo": "pais",
+ "columnsTo": [
+ "codigo"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.codigo_acceso": {
+ "name": "codigo_acceso",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "hash": {
+ "name": "hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "intentos": {
+ "name": "intentos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "usado_en": {
+ "name": "usado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "codigo_acceso_email": {
+ "name": "codigo_acceso_email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.identidad": {
+ "name": "identidad",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "proveedor": {
+ "name": "proveedor",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sujeto": {
+ "name": "sujeto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ultimo_acceso_en": {
+ "name": "ultimo_acceso_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "identidad_proveedor_sujeto": {
+ "name": "identidad_proveedor_sujeto",
+ "columns": [
+ {
+ "expression": "proveedor",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "sujeto",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "identidad_usuario": {
+ "name": "identidad_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "identidad_usuario_id_usuario_id_fk": {
+ "name": "identidad_usuario_id_usuario_id_fk",
+ "tableFrom": "identidad",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.limite": {
+ "name": "limite",
+ "schema": "",
+ "columns": {
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "intentos": {
+ "name": "intentos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "limite_expira": {
+ "name": "limite_expira",
+ "columns": [
+ {
+ "expression": "expira_en",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.sesion": {
+ "name": "sesion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "sesion_usuario": {
+ "name": "sesion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "sesion_usuario_id_usuario_id_fk": {
+ "name": "sesion_usuario_id_usuario_id_fk",
+ "tableFrom": "sesion",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usuario": {
+ "name": "usuario",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ultimo_acceso_en": {
+ "name": "ultimo_acceso_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "usuario_email_unique": {
+ "name": "usuario_email_unique",
+ "columns": [
+ "email"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.carrito": {
+ "name": "carrito",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "carrito_usuario": {
+ "name": "carrito_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "carrito_usuario_id_usuario_id_fk": {
+ "name": "carrito_usuario_id_usuario_id_fk",
+ "tableFrom": "carrito",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.carrito_item": {
+ "name": "carrito_item",
+ "schema": "",
+ "columns": {
+ "carrito_id": {
+ "name": "carrito_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "anadido_en": {
+ "name": "anadido_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "carrito_item_carrito_id_carrito_id_fk": {
+ "name": "carrito_item_carrito_id_carrito_id_fk",
+ "tableFrom": "carrito_item",
+ "columnsFrom": [
+ "carrito_id"
+ ],
+ "tableTo": "carrito",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "carrito_item_cancion_id_cancion_id_fk": {
+ "name": "carrito_item_cancion_id_cancion_id_fk",
+ "tableFrom": "carrito_item",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "carrito_item_carrito_id_cancion_id_pk": {
+ "name": "carrito_item_carrito_id_cancion_id_pk",
+ "columns": [
+ "carrito_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.compra": {
+ "name": "compra",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comprado_en": {
+ "name": "comprado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "compra_usuario_id_usuario_id_fk": {
+ "name": "compra_usuario_id_usuario_id_fk",
+ "tableFrom": "compra",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "compra_cancion_id_cancion_id_fk": {
+ "name": "compra_cancion_id_cancion_id_fk",
+ "tableFrom": "compra",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "restrict"
+ },
+ "compra_pedido_id_pedido_id_fk": {
+ "name": "compra_pedido_id_pedido_id_fk",
+ "tableFrom": "compra",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "tableTo": "pedido",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "compra_usuario_id_cancion_id_pk": {
+ "name": "compra_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pedido": {
+ "name": "pedido",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sesion_pago_id": {
+ "name": "sesion_pago_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pendiente'"
+ },
+ "packs": {
+ "name": "packs",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_centimos": {
+ "name": "total_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "moneda": {
+ "name": "moneda",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'eur'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "pagado_en": {
+ "name": "pagado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "pedido_usuario": {
+ "name": "pedido_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "pedido_usuario_id_usuario_id_fk": {
+ "name": "pedido_usuario_id_usuario_id_fk",
+ "tableFrom": "pedido",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "pedido_sesion_pago_id_unique": {
+ "name": "pedido_sesion_pago_id_unique",
+ "columns": [
+ "sesion_pago_id"
+ ],
+ "nullsNotDistinct": false
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pedido_item": {
+ "name": "pedido_item",
+ "schema": "",
+ "columns": {
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "pedido_item_pedido_id_pedido_id_fk": {
+ "name": "pedido_item_pedido_id_pedido_id_fk",
+ "tableFrom": "pedido_item",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "tableTo": "pedido",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "pedido_item_cancion_id_cancion_id_fk": {
+ "name": "pedido_item_cancion_id_cancion_id_fk",
+ "tableFrom": "pedido_item",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "restrict"
+ }
+ },
+ "compositePrimaryKeys": {
+ "pedido_item_pedido_id_cancion_id_pk": {
+ "name": "pedido_item_pedido_id_cancion_id_pk",
+ "columns": [
+ "pedido_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.favorito": {
+ "name": "favorito",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "marcado_en": {
+ "name": "marcado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_favorito_usuario": {
+ "name": "idx_favorito_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "favorito_usuario_id_usuario_id_fk": {
+ "name": "favorito_usuario_id_usuario_id_fk",
+ "tableFrom": "favorito",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "favorito_cancion_id_cancion_id_fk": {
+ "name": "favorito_cancion_id_cancion_id_fk",
+ "tableFrom": "favorito",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "favorito_usuario_id_cancion_id_pk": {
+ "name": "favorito_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.reproduccion": {
+ "name": "reproduccion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "segundos": {
+ "name": "segundos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "dia": {
+ "name": "dia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "reproduccion_dia": {
+ "name": "reproduccion_dia",
+ "columns": [
+ {
+ "expression": "dia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "reproduccion_cancion": {
+ "name": "reproduccion_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ },
+ "reproduccion_usuario": {
+ "name": "reproduccion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "reproduccion_cancion_id_cancion_id_fk": {
+ "name": "reproduccion_cancion_id_cancion_id_fk",
+ "tableFrom": "reproduccion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "reproduccion_usuario_id_usuario_id_fk": {
+ "name": "reproduccion_usuario_id_usuario_id_fk",
+ "tableFrom": "reproduccion",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "set null"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.valoracion": {
+ "name": "valoracion",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "puntuacion": {
+ "name": "puntuacion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizada_en": {
+ "name": "actualizada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_valoracion_cancion": {
+ "name": "idx_valoracion_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "with": {},
+ "method": "btree",
+ "concurrently": false
+ }
+ },
+ "foreignKeys": {
+ "valoracion_usuario_id_usuario_id_fk": {
+ "name": "valoracion_usuario_id_usuario_id_fk",
+ "tableFrom": "valoracion",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "tableTo": "usuario",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ },
+ "valoracion_cancion_id_cancion_id_fk": {
+ "name": "valoracion_cancion_id_cancion_id_fk",
+ "tableFrom": "valoracion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "tableTo": "cancion",
+ "columnsTo": [
+ "id"
+ ],
+ "onUpdate": "no action",
+ "onDelete": "cascade"
+ }
+ },
+ "compositePrimaryKeys": {
+ "valoracion_usuario_id_cancion_id_pk": {
+ "name": "valoracion_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "views": {},
+ "sequences": {},
+ "roles": {},
+ "policies": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/0017_snapshot.json b/drizzle/meta/0017_snapshot.json
new file mode 100644
index 0000000..3e38d1d
--- /dev/null
+++ b/drizzle/meta/0017_snapshot.json
@@ -0,0 +1,6968 @@
+{
+ "id": "84f697d0-cb96-441e-9013-361469bbeb3e",
+ "prevId": "89cab2aa-355f-45b2-ace8-7afc914b9b6d",
+ "version": "7",
+ "dialect": "postgresql",
+ "tables": {
+ "public.medio": {
+ "name": "medio",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "clase": {
+ "name": "clase",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "publico": {
+ "name": "publico",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "mime": {
+ "name": "mime",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bytes": {
+ "name": "bytes",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "duracion_s": {
+ "name": "duracion_s",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ancho": {
+ "name": "ancho",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "alto": {
+ "name": "alto",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sha256": {
+ "name": "sha256",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "alt": {
+ "name": "alt",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "medio_clase": {
+ "name": "medio_clase",
+ "columns": [
+ {
+ "expression": "clase",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "medio_sha": {
+ "name": "medio_sha",
+ "columns": [
+ {
+ "expression": "sha256",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "medio_clave_unique": {
+ "name": "medio_clave_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "clave"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pais": {
+ "name": "pais",
+ "schema": "",
+ "columns": {
+ "codigo": {
+ "name": "codigo",
+ "type": "char(2)",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "gentilicio": {
+ "name": "gentilicio",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "region": {
+ "name": "region",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.persona": {
+ "name": "persona",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre_legal": {
+ "name": "nombre_legal",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ipi": {
+ "name": "ipi",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nacimiento": {
+ "name": "nacimiento",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "defuncion": {
+ "name": "defuncion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "retrato_id": {
+ "name": "retrato_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "semblanza": {
+ "name": "semblanza",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "persona_nombre": {
+ "name": "persona_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "persona_pais": {
+ "name": "persona_pais",
+ "columns": [
+ {
+ "expression": "pais_codigo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "persona_pais_codigo_pais_codigo_fk": {
+ "name": "persona_pais_codigo_pais_codigo_fk",
+ "tableFrom": "persona",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "persona_retrato_id_medio_id_fk": {
+ "name": "persona_retrato_id_medio_id_fk",
+ "tableFrom": "persona",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "retrato_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "persona_slug_unique": {
+ "name": "persona_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.artista": {
+ "name": "artista",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'ART-' || lpad(nextval('artista_codigo_seq')::text, 6, '0')"
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'persona'"
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "descripcion_corta": {
+ "name": "descripcion_corta",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "biografia": {
+ "name": "biografia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "lugar_origen": {
+ "name": "lugar_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "inicio": {
+ "name": "inicio",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "fin": {
+ "name": "fin",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sitio_web": {
+ "name": "sitio_web",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "artista_codigo_unico": {
+ "name": "artista_codigo_unico",
+ "columns": [
+ {
+ "expression": "codigo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "artista_slug_unico": {
+ "name": "artista_slug_unico",
+ "columns": [
+ {
+ "expression": "slug",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "artista_nombre": {
+ "name": "artista_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "artista_estado": {
+ "name": "artista_estado",
+ "columns": [
+ {
+ "expression": "estado",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "artista_imagen_id_medio_id_fk": {
+ "name": "artista_imagen_id_medio_id_fk",
+ "tableFrom": "artista",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "artista_pais_codigo_pais_codigo_fk": {
+ "name": "artista_pais_codigo_pais_codigo_fk",
+ "tableFrom": "artista",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "artista_tipo_conocido": {
+ "name": "artista_tipo_conocido",
+ "value": "\"artista\".\"tipo\" in ('persona', 'grupo', 'proyecto')"
+ },
+ "artista_estado_conocido": {
+ "name": "artista_estado_conocido",
+ "value": "\"artista\".\"estado\" in ('borrador', 'publicado', 'retirado')"
+ },
+ "artista_periodo_valido": {
+ "name": "artista_periodo_valido",
+ "value": "\"artista\".\"fin\" is null or \"artista\".\"inicio\" is null or \"artista\".\"fin\" >= \"artista\".\"inicio\""
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.artista_identificador": {
+ "name": "artista_identificador",
+ "schema": "",
+ "columns": {
+ "artista_id": {
+ "name": "artista_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sistema": {
+ "name": "sistema",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "valor": {
+ "name": "valor",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "artista_identificador_externo_unico": {
+ "name": "artista_identificador_externo_unico",
+ "columns": [
+ {
+ "expression": "sistema",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "valor",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "artista_identificador_artista_id_artista_id_fk": {
+ "name": "artista_identificador_artista_id_artista_id_fk",
+ "tableFrom": "artista_identificador",
+ "tableTo": "artista",
+ "columnsFrom": [
+ "artista_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "artista_identificador_artista_id_sistema_pk": {
+ "name": "artista_identificador_artista_id_sistema_pk",
+ "columns": [
+ "artista_id",
+ "sistema"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.artista_persona": {
+ "name": "artista_persona",
+ "schema": "",
+ "columns": {
+ "artista_id": {
+ "name": "artista_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "relacion": {
+ "name": "relacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "desde": {
+ "name": "desde",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "hasta": {
+ "name": "hasta",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "artista_persona_persona": {
+ "name": "artista_persona_persona",
+ "columns": [
+ {
+ "expression": "persona_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "artista_persona_artista_id_artista_id_fk": {
+ "name": "artista_persona_artista_id_artista_id_fk",
+ "tableFrom": "artista_persona",
+ "tableTo": "artista",
+ "columnsFrom": [
+ "artista_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "artista_persona_persona_id_persona_id_fk": {
+ "name": "artista_persona_persona_id_persona_id_fk",
+ "tableFrom": "artista_persona",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "artista_persona_artista_id_persona_id_relacion_pk": {
+ "name": "artista_persona_artista_id_persona_id_relacion_pk",
+ "columns": [
+ "artista_id",
+ "persona_id",
+ "relacion"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "artista_persona_periodo_valido": {
+ "name": "artista_persona_periodo_valido",
+ "value": "\"artista_persona\".\"hasta\" is null or \"artista_persona\".\"desde\" is null or \"artista_persona\".\"hasta\" >= \"artista_persona\".\"desde\""
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.album": {
+ "name": "album",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estilo_id": {
+ "name": "estilo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'album'"
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "portada_id": {
+ "name": "portada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "sello": {
+ "name": "sello",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "destacado": {
+ "name": "destacado",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "numero_catalogo": {
+ "name": "numero_catalogo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "formatos": {
+ "name": "formatos",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_edicion_codigo": {
+ "name": "pais_edicion_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "album_estilo": {
+ "name": "album_estilo",
+ "columns": [
+ {
+ "expression": "estilo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "album_fecha": {
+ "name": "album_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "album_estilo_id_estilo_id_fk": {
+ "name": "album_estilo_id_estilo_id_fk",
+ "tableFrom": "album",
+ "tableTo": "estilo",
+ "columnsFrom": [
+ "estilo_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "album_portada_id_medio_id_fk": {
+ "name": "album_portada_id_medio_id_fk",
+ "tableFrom": "album",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "portada_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "album_pais_edicion_codigo_pais_codigo_fk": {
+ "name": "album_pais_edicion_codigo_pais_codigo_fk",
+ "tableFrom": "album",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_edicion_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "album_slug_unique": {
+ "name": "album_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.album_enlace": {
+ "name": "album_enlace",
+ "schema": "",
+ "columns": {
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "album_enlace_album_id_album_id_fk": {
+ "name": "album_enlace_album_id_album_id_fk",
+ "tableFrom": "album_enlace",
+ "tableTo": "album",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "album_enlace_album_id_plataforma_pk": {
+ "name": "album_enlace_album_id_plataforma_pk",
+ "columns": [
+ "album_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.autoria": {
+ "name": "autoria",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "porcentaje": {
+ "name": "porcentaje",
+ "type": "numeric(5, 2)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "autoria_cancion_id_cancion_id_fk": {
+ "name": "autoria_cancion_id_cancion_id_fk",
+ "tableFrom": "autoria",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "autoria_persona_id_persona_id_fk": {
+ "name": "autoria_persona_id_persona_id_fk",
+ "tableFrom": "autoria",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "autoria_cancion_id_persona_id_rol_pk": {
+ "name": "autoria_cancion_id_persona_id_rol_pk",
+ "columns": [
+ "cancion_id",
+ "persona_id",
+ "rol"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion": {
+ "name": "cancion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'CAN-' || lpad(nextval('cancion_codigo_seq')::text, 6, '0')"
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "version_de_id": {
+ "name": "version_de_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_nombre": {
+ "name": "version_nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_nota": {
+ "name": "version_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_codigo": {
+ "name": "version_codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "version_orden": {
+ "name": "version_orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "estilo_id": {
+ "name": "estilo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "audio_id": {
+ "name": "audio_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "muestra_id": {
+ "name": "muestra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "duracion_s": {
+ "name": "duracion_s",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ano": {
+ "name": "ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "letra": {
+ "name": "letra",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'es'"
+ },
+ "inspiracion": {
+ "name": "inspiracion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "instrumental": {
+ "name": "instrumental",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "destacada": {
+ "name": "destacada",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "portada_id": {
+ "name": "portada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ala_venta": {
+ "name": "ala_venta",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "cancion_codigo_unico": {
+ "name": "cancion_codigo_unico",
+ "columns": [
+ {
+ "expression": "codigo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_estilo": {
+ "name": "cancion_estilo",
+ "columns": [
+ {
+ "expression": "estilo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_album": {
+ "name": "cancion_album",
+ "columns": [
+ {
+ "expression": "album_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_version_de": {
+ "name": "cancion_version_de",
+ "columns": [
+ {
+ "expression": "version_de_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_destacada": {
+ "name": "cancion_destacada",
+ "columns": [
+ {
+ "expression": "destacada",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_version_codigo_unico": {
+ "name": "cancion_version_codigo_unico",
+ "columns": [
+ {
+ "expression": "version_de_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "version_codigo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "where": "\"cancion\".\"version_de_id\" is not null",
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "cancion_estilo_id_estilo_id_fk": {
+ "name": "cancion_estilo_id_estilo_id_fk",
+ "tableFrom": "cancion",
+ "tableTo": "estilo",
+ "columnsFrom": [
+ "estilo_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "cancion_album_id_album_id_fk": {
+ "name": "cancion_album_id_album_id_fk",
+ "tableFrom": "cancion",
+ "tableTo": "album",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "cancion_audio_id_medio_id_fk": {
+ "name": "cancion_audio_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "audio_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "cancion_muestra_id_medio_id_fk": {
+ "name": "cancion_muestra_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "muestra_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "cancion_portada_id_medio_id_fk": {
+ "name": "cancion_portada_id_medio_id_fk",
+ "tableFrom": "cancion",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "portada_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "cancion_slug_unique": {
+ "name": "cancion_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {
+ "cancion_version_codigo_presente": {
+ "name": "cancion_version_codigo_presente",
+ "value": "(\"cancion\".\"version_de_id\" is null and \"cancion\".\"version_codigo\" is null) or (\"cancion\".\"version_de_id\" is not null and nullif(btrim(\"cancion\".\"version_codigo\"), '') is not null)"
+ },
+ "cancion_version_no_se_vende": {
+ "name": "cancion_version_no_se_vende",
+ "value": "\"cancion\".\"version_de_id\" is null or not \"cancion\".\"ala_venta\""
+ },
+ "cancion_estado_conocido": {
+ "name": "cancion_estado_conocido",
+ "value": "\"cancion\".\"estado\" in ('borrador', 'publicado', 'retirado')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.cancion_audio": {
+ "name": "cancion_audio",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "medio_id": {
+ "name": "medio_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "uso": {
+ "name": "uso",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "formato": {
+ "name": "formato",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bitrate_kbps": {
+ "name": "bitrate_kbps",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "frecuencia_hz": {
+ "name": "frecuencia_hz",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "bits_muestra": {
+ "name": "bits_muestra",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "canales": {
+ "name": "canales",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "cancion_audio_medio_unico": {
+ "name": "cancion_audio_medio_unico",
+ "columns": [
+ {
+ "expression": "medio_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "cancion_audio_cancion": {
+ "name": "cancion_audio_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "cancion_audio_cancion_id_cancion_id_fk": {
+ "name": "cancion_audio_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_audio",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "cancion_audio_medio_id_medio_id_fk": {
+ "name": "cancion_audio_medio_id_medio_id_fk",
+ "tableFrom": "cancion_audio",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "medio_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_audio_cancion_id_uso_formato_pk": {
+ "name": "cancion_audio_cancion_id_uso_formato_pk",
+ "columns": [
+ "cancion_id",
+ "uso",
+ "formato"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "cancion_audio_uso_conocido": {
+ "name": "cancion_audio_uso_conocido",
+ "value": "\"cancion_audio\".\"uso\" in ('stream', 'descarga', 'master')"
+ },
+ "cancion_audio_bitrate_valido": {
+ "name": "cancion_audio_bitrate_valido",
+ "value": "\"cancion_audio\".\"bitrate_kbps\" is null or \"cancion_audio\".\"bitrate_kbps\" > 0"
+ },
+ "cancion_audio_frecuencia_valida": {
+ "name": "cancion_audio_frecuencia_valida",
+ "value": "\"cancion_audio\".\"frecuencia_hz\" is null or \"cancion_audio\".\"frecuencia_hz\" > 0"
+ },
+ "cancion_audio_bits_validos": {
+ "name": "cancion_audio_bits_validos",
+ "value": "\"cancion_audio\".\"bits_muestra\" is null or \"cancion_audio\".\"bits_muestra\" > 0"
+ },
+ "cancion_audio_canales_validos": {
+ "name": "cancion_audio_canales_validos",
+ "value": "\"cancion_audio\".\"canales\" is null or \"cancion_audio\".\"canales\" > 0"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.cancion_enlace": {
+ "name": "cancion_enlace",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_enlace_cancion_id_cancion_id_fk": {
+ "name": "cancion_enlace_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_enlace",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_enlace_cancion_id_plataforma_pk": {
+ "name": "cancion_enlace_cancion_id_plataforma_pk",
+ "columns": [
+ "cancion_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_etiqueta": {
+ "name": "cancion_etiqueta",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_etiqueta_cancion_id_cancion_id_fk": {
+ "name": "cancion_etiqueta_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_etiqueta",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "cancion_etiqueta_etiqueta_id_etiqueta_id_fk": {
+ "name": "cancion_etiqueta_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "cancion_etiqueta",
+ "tableTo": "etiqueta",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_etiqueta_cancion_id_etiqueta_id_pk": {
+ "name": "cancion_etiqueta_cancion_id_etiqueta_id_pk",
+ "columns": [
+ "cancion_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_interprete": {
+ "name": "cancion_interprete",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "artista_id": {
+ "name": "artista_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'principal'"
+ },
+ "instrumento": {
+ "name": "instrumento",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "acreditado_como": {
+ "name": "acreditado_como",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "cancion_interprete_artista": {
+ "name": "cancion_interprete_artista",
+ "columns": [
+ {
+ "expression": "artista_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "cancion_interprete_cancion_id_cancion_id_fk": {
+ "name": "cancion_interprete_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_interprete",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "cancion_interprete_artista_id_artista_id_fk": {
+ "name": "cancion_interprete_artista_id_artista_id_fk",
+ "tableFrom": "cancion_interprete",
+ "tableTo": "artista",
+ "columnsFrom": [
+ "artista_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_interprete_cancion_id_artista_id_rol_pk": {
+ "name": "cancion_interprete_cancion_id_artista_id_rol_pk",
+ "columns": [
+ "cancion_id",
+ "artista_id",
+ "rol"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {
+ "cancion_interprete_rol_conocido": {
+ "name": "cancion_interprete_rol_conocido",
+ "value": "\"cancion_interprete\".\"rol\" in ('principal', 'invitado', 'coros', 'instrumentista')"
+ }
+ },
+ "isRLSEnabled": false
+ },
+ "public.cancion_persona": {
+ "name": "cancion_persona",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_persona_cancion_id_cancion_id_fk": {
+ "name": "cancion_persona_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_persona",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "cancion_persona_persona_id_persona_id_fk": {
+ "name": "cancion_persona_persona_id_persona_id_fk",
+ "tableFrom": "cancion_persona",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_persona_cancion_id_persona_id_rol_pk": {
+ "name": "cancion_persona_cancion_id_persona_id_rol_pk",
+ "columns": [
+ "cancion_id",
+ "persona_id",
+ "rol"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.credito_album": {
+ "name": "credito_album",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "album_id": {
+ "name": "album_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "credito_album_album": {
+ "name": "credito_album_album",
+ "columns": [
+ {
+ "expression": "album_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "credito_album_album_id_album_id_fk": {
+ "name": "credito_album_album_id_album_id_fk",
+ "tableFrom": "credito_album",
+ "tableTo": "album",
+ "columnsFrom": [
+ "album_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "credito_album_persona_id_persona_id_fk": {
+ "name": "credito_album_persona_id_persona_id_fk",
+ "tableFrom": "credito_album",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.estilo": {
+ "name": "estilo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "estilo_principal_unico": {
+ "name": "estilo_principal_unico",
+ "columns": [
+ {
+ "expression": "principal",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "where": "\"estilo\".\"principal\"",
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "estilo_orden": {
+ "name": "estilo_orden",
+ "columns": [
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "estilo_imagen_id_medio_id_fk": {
+ "name": "estilo_imagen_id_medio_id_fk",
+ "tableFrom": "estilo",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "estilo_slug_unique": {
+ "name": "estilo_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.etiqueta": {
+ "name": "etiqueta",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "etiqueta_slug_unique": {
+ "name": "etiqueta_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.registro_obra": {
+ "name": "registro_obra",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "iswc": {
+ "name": "iswc",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "isrc": {
+ "name": "isrc",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "entidad": {
+ "name": "entidad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numero": {
+ "name": "numero",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "editorial": {
+ "name": "editorial",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "registro_obra_cancion_id_cancion_id_fk": {
+ "name": "registro_obra_cancion_id_cancion_id_fk",
+ "tableFrom": "registro_obra",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.traduccion": {
+ "name": "traduccion",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "texto": {
+ "name": "texto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "traduccion_cancion_id_cancion_id_fk": {
+ "name": "traduccion_cancion_id_cancion_id_fk",
+ "tableFrom": "traduccion",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "traduccion_cancion_id_idioma_pk": {
+ "name": "traduccion_cancion_id_idioma_pk",
+ "columns": [
+ "cancion_id",
+ "idioma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.video": {
+ "name": "video",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "youtube_id": {
+ "name": "youtube_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "video_cancion": {
+ "name": "video_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "video_cancion_id_cancion_id_fk": {
+ "name": "video_cancion_id_cancion_id_fk",
+ "tableFrom": "video",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.acepcion": {
+ "name": "acepcion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "categoria": {
+ "name": "categoria",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "definicion": {
+ "name": "definicion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ampliacion": {
+ "name": "ampliacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ejemplo": {
+ "name": "ejemplo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "acepcion_numero": {
+ "name": "acepcion_numero",
+ "columns": [
+ {
+ "expression": "termino_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "numero",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "acepcion_termino_id_termino_id_fk": {
+ "name": "acepcion_termino_id_termino_id_fk",
+ "tableFrom": "acepcion",
+ "tableTo": "termino",
+ "columnsFrom": [
+ "termino_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.animo": {
+ "name": "animo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "gems": {
+ "name": "gems",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valencia": {
+ "name": "valencia",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "energia": {
+ "name": "energia",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "animo_codigo_unique": {
+ "name": "animo_codigo_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "codigo"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.cancion_genero": {
+ "name": "cancion_genero",
+ "schema": "",
+ "columns": {
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "cancion_genero_cancion_id_cancion_id_fk": {
+ "name": "cancion_genero_cancion_id_cancion_id_fk",
+ "tableFrom": "cancion_genero",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "cancion_genero_genero_id_genero_id_fk": {
+ "name": "cancion_genero_genero_id_genero_id_fk",
+ "tableFrom": "cancion_genero",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "cancion_genero_cancion_id_genero_id_pk": {
+ "name": "cancion_genero_cancion_id_genero_id_pk",
+ "columns": [
+ "cancion_id",
+ "genero_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.capitulo": {
+ "name": "capitulo",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "capitulo_tipo": {
+ "name": "capitulo_tipo",
+ "columns": [
+ {
+ "expression": "tipo",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "capitulo_genero_id_genero_id_fk": {
+ "name": "capitulo_genero_id_genero_id_fk",
+ "tableFrom": "capitulo",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "capitulo_slug_unique": {
+ "name": "capitulo_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.capitulo_acepcion": {
+ "name": "capitulo_acepcion",
+ "schema": "",
+ "columns": {
+ "capitulo_id": {
+ "name": "capitulo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "acepcion_id": {
+ "name": "acepcion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "automatico": {
+ "name": "automatico",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "confirmado": {
+ "name": "confirmado",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "capitulo_acepcion_capitulo_id_capitulo_id_fk": {
+ "name": "capitulo_acepcion_capitulo_id_capitulo_id_fk",
+ "tableFrom": "capitulo_acepcion",
+ "tableTo": "capitulo",
+ "columnsFrom": [
+ "capitulo_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "capitulo_acepcion_acepcion_id_acepcion_id_fk": {
+ "name": "capitulo_acepcion_acepcion_id_acepcion_id_fk",
+ "tableFrom": "capitulo_acepcion",
+ "tableTo": "acepcion",
+ "columnsFrom": [
+ "acepcion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "capitulo_acepcion_capitulo_id_acepcion_id_pk": {
+ "name": "capitulo_acepcion_capitulo_id_acepcion_id_pk",
+ "columns": [
+ "capitulo_id",
+ "acepcion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.compas": {
+ "name": "compas",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "numerador": {
+ "name": "numerador",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "denominador": {
+ "name": "denominador",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "compas_codigo_unique": {
+ "name": "compas_codigo_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "codigo"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero": {
+ "name": "genero",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "origen_lugar": {
+ "name": "origen_lugar",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "origen_ano": {
+ "name": "origen_ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tempo": {
+ "name": "tempo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "metrica_nota": {
+ "name": "metrica_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "compas_nota": {
+ "name": "compas_nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rasgos": {
+ "name": "rasgos",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "genero_nombre": {
+ "name": "genero_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "genero_origen_ano": {
+ "name": "genero_origen_ano",
+ "columns": [
+ {
+ "expression": "origen_ano",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "genero_slug_unique": {
+ "name": "genero_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_alias": {
+ "name": "genero_alias",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "genero_alias_nombre": {
+ "name": "genero_alias_nombre",
+ "columns": [
+ {
+ "expression": "nombre",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "genero_alias_genero_id_genero_id_fk": {
+ "name": "genero_alias_genero_id_genero_id_fk",
+ "tableFrom": "genero_alias",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_alias_pais_codigo_pais_codigo_fk": {
+ "name": "genero_alias_pais_codigo_pais_codigo_fk",
+ "tableFrom": "genero_alias",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_compas": {
+ "name": "genero_compas",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "compas_id": {
+ "name": "compas_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_compas_genero_id_genero_id_fk": {
+ "name": "genero_compas_genero_id_genero_id_fk",
+ "tableFrom": "genero_compas",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_compas_compas_id_compas_id_fk": {
+ "name": "genero_compas_compas_id_compas_id_fk",
+ "tableFrom": "genero_compas",
+ "tableTo": "compas",
+ "columnsFrom": [
+ "compas_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_compas_genero_id_compas_id_pk": {
+ "name": "genero_compas_genero_id_compas_id_pk",
+ "columns": [
+ "genero_id",
+ "compas_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_instrumento": {
+ "name": "genero_instrumento",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "instrumento_id": {
+ "name": "instrumento_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "importancia": {
+ "name": "importancia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'habitual'"
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_instrumento_genero_id_genero_id_fk": {
+ "name": "genero_instrumento_genero_id_genero_id_fk",
+ "tableFrom": "genero_instrumento",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_instrumento_instrumento_id_instrumento_id_fk": {
+ "name": "genero_instrumento_instrumento_id_instrumento_id_fk",
+ "tableFrom": "genero_instrumento",
+ "tableTo": "instrumento",
+ "columnsFrom": [
+ "instrumento_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_instrumento_genero_id_instrumento_id_pk": {
+ "name": "genero_instrumento_genero_id_instrumento_id_pk",
+ "columns": [
+ "genero_id",
+ "instrumento_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_metro": {
+ "name": "genero_metro",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "metro_id": {
+ "name": "metro_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "predominante": {
+ "name": "predominante",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_metro_genero_id_genero_id_fk": {
+ "name": "genero_metro_genero_id_genero_id_fk",
+ "tableFrom": "genero_metro",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_metro_metro_id_metro_id_fk": {
+ "name": "genero_metro_metro_id_metro_id_fk",
+ "tableFrom": "genero_metro",
+ "tableTo": "metro",
+ "columnsFrom": [
+ "metro_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_metro_genero_id_metro_id_pk": {
+ "name": "genero_metro_genero_id_metro_id_pk",
+ "columns": [
+ "genero_id",
+ "metro_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_origen": {
+ "name": "genero_origen",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "origen_id": {
+ "name": "origen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "principal": {
+ "name": "principal",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "genero_origen_origen": {
+ "name": "genero_origen_origen",
+ "columns": [
+ {
+ "expression": "origen_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "genero_origen_genero_id_genero_id_fk": {
+ "name": "genero_origen_genero_id_genero_id_fk",
+ "tableFrom": "genero_origen",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_origen_origen_id_genero_id_fk": {
+ "name": "genero_origen_origen_id_genero_id_fk",
+ "tableFrom": "genero_origen",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "origen_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_origen_genero_id_origen_id_tipo_pk": {
+ "name": "genero_origen_genero_id_origen_id_tipo_pk",
+ "columns": [
+ "genero_id",
+ "origen_id",
+ "tipo"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_pais": {
+ "name": "genero_pais",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "relacion": {
+ "name": "relacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'adoptado'"
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_pais_genero_id_genero_id_fk": {
+ "name": "genero_pais_genero_id_genero_id_fk",
+ "tableFrom": "genero_pais",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_pais_pais_codigo_pais_codigo_fk": {
+ "name": "genero_pais_pais_codigo_pais_codigo_fk",
+ "tableFrom": "genero_pais",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_pais_genero_id_pais_codigo_pk": {
+ "name": "genero_pais_genero_id_pais_codigo_pk",
+ "columns": [
+ "genero_id",
+ "pais_codigo"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_persona": {
+ "name": "genero_persona",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_persona_genero_id_genero_id_fk": {
+ "name": "genero_persona_genero_id_genero_id_fk",
+ "tableFrom": "genero_persona",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_persona_persona_id_persona_id_fk": {
+ "name": "genero_persona_persona_id_persona_id_fk",
+ "tableFrom": "genero_persona",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_persona_genero_id_persona_id_papel_pk": {
+ "name": "genero_persona_genero_id_persona_id_papel_pk",
+ "columns": [
+ "genero_id",
+ "persona_id",
+ "papel"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_seccion": {
+ "name": "genero_seccion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {
+ "genero_seccion_clave": {
+ "name": "genero_seccion_clave",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "clave",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "genero_seccion_genero_id_genero_id_fk": {
+ "name": "genero_seccion_genero_id_genero_id_fk",
+ "tableFrom": "genero_seccion",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.genero_tema": {
+ "name": "genero_tema",
+ "schema": "",
+ "columns": {
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "genero_tema_genero_id_genero_id_fk": {
+ "name": "genero_tema_genero_id_genero_id_fk",
+ "tableFrom": "genero_tema",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "genero_tema_etiqueta_id_etiqueta_id_fk": {
+ "name": "genero_tema_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "genero_tema",
+ "tableTo": "etiqueta",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "genero_tema_genero_id_etiqueta_id_pk": {
+ "name": "genero_tema_genero_id_etiqueta_id_pk",
+ "columns": [
+ "genero_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.instrumento": {
+ "name": "instrumento",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "familia": {
+ "name": "familia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "subfamilia": {
+ "name": "subfamilia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "afinacion": {
+ "name": "afinacion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "muestra_id": {
+ "name": "muestra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "instrumento_familia": {
+ "name": "instrumento_familia",
+ "columns": [
+ {
+ "expression": "familia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "instrumento_pais_codigo_pais_codigo_fk": {
+ "name": "instrumento_pais_codigo_pais_codigo_fk",
+ "tableFrom": "instrumento",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "instrumento_imagen_id_medio_id_fk": {
+ "name": "instrumento_imagen_id_medio_id_fk",
+ "tableFrom": "instrumento",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "instrumento_muestra_id_medio_id_fk": {
+ "name": "instrumento_muestra_id_medio_id_fk",
+ "tableFrom": "instrumento",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "muestra_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "instrumento_slug_unique": {
+ "name": "instrumento_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.metro": {
+ "name": "metro",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "silabas": {
+ "name": "silabas",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "metro_codigo_unique": {
+ "name": "metro_codigo_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "codigo"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.modelo_ia": {
+ "name": "modelo_ia",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "codigo": {
+ "name": "codigo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "familia": {
+ "name": "familia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "version": {
+ "name": "version",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vigente": {
+ "name": "vigente",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "nota_sintaxis": {
+ "name": "nota_sintaxis",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "esquema": {
+ "name": "esquema",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "modelo_ia_familia": {
+ "name": "modelo_ia_familia",
+ "columns": [
+ {
+ "expression": "familia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "modelo_ia_codigo_unique": {
+ "name": "modelo_ia_codigo_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "codigo"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia": {
+ "name": "obra_referencia",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ano": {
+ "name": "ano",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "nota": {
+ "name": "nota",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cita": {
+ "name": "cita",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "obra_referencia_genero": {
+ "name": "obra_referencia_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "obra_referencia_genero_id_genero_id_fk": {
+ "name": "obra_referencia_genero_id_genero_id_fk",
+ "tableFrom": "obra_referencia",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "obra_referencia_slug_unique": {
+ "name": "obra_referencia_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia_enlace": {
+ "name": "obra_referencia_enlace",
+ "schema": "",
+ "columns": {
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "plataforma": {
+ "name": "plataforma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "url": {
+ "name": "url",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "obra_referencia_enlace_obra_id_obra_referencia_id_fk": {
+ "name": "obra_referencia_enlace_obra_id_obra_referencia_id_fk",
+ "tableFrom": "obra_referencia_enlace",
+ "tableTo": "obra_referencia",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "obra_referencia_enlace_obra_id_plataforma_pk": {
+ "name": "obra_referencia_enlace_obra_id_plataforma_pk",
+ "columns": [
+ "obra_id",
+ "plataforma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.obra_referencia_persona": {
+ "name": "obra_referencia_persona",
+ "schema": "",
+ "columns": {
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "persona_id": {
+ "name": "persona_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "papel": {
+ "name": "papel",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "obra_referencia_persona_obra_id_obra_referencia_id_fk": {
+ "name": "obra_referencia_persona_obra_id_obra_referencia_id_fk",
+ "tableFrom": "obra_referencia_persona",
+ "tableTo": "obra_referencia",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "obra_referencia_persona_persona_id_persona_id_fk": {
+ "name": "obra_referencia_persona_persona_id_persona_id_fk",
+ "tableFrom": "obra_referencia_persona",
+ "tableTo": "persona",
+ "columnsFrom": [
+ "persona_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "obra_referencia_persona_obra_id_persona_id_papel_pk": {
+ "name": "obra_referencia_persona_obra_id_persona_id_papel_pk",
+ "columns": [
+ "obra_id",
+ "persona_id",
+ "papel"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.prompt": {
+ "name": "prompt",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "modelo_ia_id": {
+ "name": "modelo_ia_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "animo_id": {
+ "name": "animo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "idioma": {
+ "name": "idioma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'en'"
+ },
+ "contenido": {
+ "name": "contenido",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "notas": {
+ "name": "notas",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "valoracion": {
+ "name": "valoracion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ejemplo_id": {
+ "name": "ejemplo_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "preferido": {
+ "name": "preferido",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "visibilidad": {
+ "name": "visibilidad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'privado'"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "prompt_genero": {
+ "name": "prompt_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "prompt_cancion": {
+ "name": "prompt_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "prompt_modelo": {
+ "name": "prompt_modelo",
+ "columns": [
+ {
+ "expression": "modelo_ia_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "prompt_animo": {
+ "name": "prompt_animo",
+ "columns": [
+ {
+ "expression": "animo_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "prompt_modelo_ia_id_modelo_ia_id_fk": {
+ "name": "prompt_modelo_ia_id_modelo_ia_id_fk",
+ "tableFrom": "prompt",
+ "tableTo": "modelo_ia",
+ "columnsFrom": [
+ "modelo_ia_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "prompt_genero_id_genero_id_fk": {
+ "name": "prompt_genero_id_genero_id_fk",
+ "tableFrom": "prompt",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "prompt_cancion_id_cancion_id_fk": {
+ "name": "prompt_cancion_id_cancion_id_fk",
+ "tableFrom": "prompt",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "prompt_animo_id_animo_id_fk": {
+ "name": "prompt_animo_id_animo_id_fk",
+ "tableFrom": "prompt",
+ "tableTo": "animo",
+ "columnsFrom": [
+ "animo_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "prompt_ejemplo_id_medio_id_fk": {
+ "name": "prompt_ejemplo_id_medio_id_fk",
+ "tableFrom": "prompt",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "ejemplo_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.termino": {
+ "name": "termino",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "termino": {
+ "name": "termino",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "termino_slug_unique": {
+ "name": "termino_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ },
+ "termino_termino_unique": {
+ "name": "termino_termino_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "termino"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.termino_variante": {
+ "name": "termino_variante",
+ "schema": "",
+ "columns": {
+ "termino_id": {
+ "name": "termino_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "forma": {
+ "name": "forma",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "termino_variante_termino_id_termino_id_fk": {
+ "name": "termino_variante_termino_id_termino_id_fk",
+ "tableFrom": "termino_variante",
+ "tableTo": "termino",
+ "columnsFrom": [
+ "termino_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "termino_variante_termino_id_forma_pk": {
+ "name": "termino_variante_termino_id_forma_pk",
+ "columns": [
+ "termino_id",
+ "forma"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.verso": {
+ "name": "verso",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "genero_id": {
+ "name": "genero_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "ilustra": {
+ "name": "ilustra",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "fuente": {
+ "name": "fuente",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'ejemplo'"
+ },
+ "analisis": {
+ "name": "analisis",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "medida": {
+ "name": "medida",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "obra_id": {
+ "name": "obra_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "origen": {
+ "name": "origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'manual'"
+ },
+ "modelo_origen": {
+ "name": "modelo_origen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "importado_en": {
+ "name": "importado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_por": {
+ "name": "revisado_por",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "revisado_en": {
+ "name": "revisado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "verso_genero": {
+ "name": "verso_genero",
+ "columns": [
+ {
+ "expression": "genero_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "orden",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "verso_genero_id_genero_id_fk": {
+ "name": "verso_genero_id_genero_id_fk",
+ "tableFrom": "verso",
+ "tableTo": "genero",
+ "columnsFrom": [
+ "genero_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "verso_obra_id_obra_referencia_id_fk": {
+ "name": "verso_obra_id_obra_referencia_id_fk",
+ "tableFrom": "verso",
+ "tableTo": "obra_referencia",
+ "columnsFrom": [
+ "obra_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ },
+ "verso_cancion_id_cancion_id_fk": {
+ "name": "verso_cancion_id_cancion_id_fk",
+ "tableFrom": "verso",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.verso_linea": {
+ "name": "verso_linea",
+ "schema": "",
+ "columns": {
+ "verso_id": {
+ "name": "verso_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "texto": {
+ "name": "texto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "silabas": {
+ "name": "silabas",
+ "type": "text[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "tonicas": {
+ "name": "tonicas",
+ "type": "integer[]",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "medida": {
+ "name": "medida",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rima": {
+ "name": "rima",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "verso_linea_verso_id_verso_id_fk": {
+ "name": "verso_linea_verso_id_verso_id_fk",
+ "tableFrom": "verso_linea",
+ "tableTo": "verso",
+ "columnsFrom": [
+ "verso_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "verso_linea_verso_id_numero_pk": {
+ "name": "verso_linea_verso_id_numero_pk",
+ "columns": [
+ "verso_id",
+ "numero"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.documento_legal": {
+ "name": "documento_legal",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "orden": {
+ "name": "orden",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "version_vigente_id": {
+ "name": "version_vigente_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "documento_legal_slug_unique": {
+ "name": "documento_legal_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada": {
+ "name": "entrada",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "resumen": {
+ "name": "resumen",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "imagen_id": {
+ "name": "imagen_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "entrada_fecha": {
+ "name": "entrada_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "entrada_imagen_id_medio_id_fk": {
+ "name": "entrada_imagen_id_medio_id_fk",
+ "tableFrom": "entrada",
+ "tableTo": "medio",
+ "columnsFrom": [
+ "imagen_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "entrada_slug_unique": {
+ "name": "entrada_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada_cancion": {
+ "name": "entrada_cancion",
+ "schema": "",
+ "columns": {
+ "entrada_id": {
+ "name": "entrada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "entrada_cancion_entrada_id_entrada_id_fk": {
+ "name": "entrada_cancion_entrada_id_entrada_id_fk",
+ "tableFrom": "entrada_cancion",
+ "tableTo": "entrada",
+ "columnsFrom": [
+ "entrada_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "entrada_cancion_cancion_id_cancion_id_fk": {
+ "name": "entrada_cancion_cancion_id_cancion_id_fk",
+ "tableFrom": "entrada_cancion",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "entrada_cancion_entrada_id_cancion_id_pk": {
+ "name": "entrada_cancion_entrada_id_cancion_id_pk",
+ "columns": [
+ "entrada_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.entrada_etiqueta": {
+ "name": "entrada_etiqueta",
+ "schema": "",
+ "columns": {
+ "entrada_id": {
+ "name": "entrada_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "etiqueta_id": {
+ "name": "etiqueta_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "entrada_etiqueta_entrada_id_entrada_id_fk": {
+ "name": "entrada_etiqueta_entrada_id_entrada_id_fk",
+ "tableFrom": "entrada_etiqueta",
+ "tableTo": "entrada",
+ "columnsFrom": [
+ "entrada_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "entrada_etiqueta_etiqueta_id_etiqueta_id_fk": {
+ "name": "entrada_etiqueta_etiqueta_id_etiqueta_id_fk",
+ "tableFrom": "entrada_etiqueta",
+ "tableTo": "etiqueta",
+ "columnsFrom": [
+ "etiqueta_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "entrada_etiqueta_entrada_id_etiqueta_id_pk": {
+ "name": "entrada_etiqueta_entrada_id_etiqueta_id_pk",
+ "columns": [
+ "entrada_id",
+ "etiqueta_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pagina": {
+ "name": "pagina",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "slug": {
+ "name": "slug",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "descripcion": {
+ "name": "descripcion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "''"
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'borrador'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "pagina_slug_unique": {
+ "name": "pagina_slug_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "slug"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.redireccion": {
+ "name": "redireccion",
+ "schema": "",
+ "columns": {
+ "desde": {
+ "name": "desde",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "hacia": {
+ "name": "hacia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "permanente": {
+ "name": "permanente",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": true
+ },
+ "motivo": {
+ "name": "motivo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "redireccion_hacia": {
+ "name": "redireccion_hacia",
+ "columns": [
+ {
+ "expression": "hacia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.version_legal": {
+ "name": "version_legal",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "documento_id": {
+ "name": "documento_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cuerpo": {
+ "name": "cuerpo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "vigente_desde": {
+ "name": "vigente_desde",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "resumen_cambios": {
+ "name": "resumen_cambios",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "version_legal_documento": {
+ "name": "version_legal_documento",
+ "columns": [
+ {
+ "expression": "documento_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "vigente_desde",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "version_legal_documento_id_documento_legal_id_fk": {
+ "name": "version_legal_documento_id_documento_legal_id_fk",
+ "tableFrom": "version_legal",
+ "tableTo": "documento_legal",
+ "columnsFrom": [
+ "documento_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.contador_factura": {
+ "name": "contador_factura",
+ "schema": "",
+ "columns": {
+ "serie": {
+ "name": "serie",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "ultimo_numero": {
+ "name": "ultimo_numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.datos_facturacion": {
+ "name": "datos_facturacion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'particular'"
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nif": {
+ "name": "nif",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "direccion": {
+ "name": "direccion",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "cp": {
+ "name": "cp",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "ciudad": {
+ "name": "ciudad",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "provincia": {
+ "name": "provincia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "predeterminada": {
+ "name": "predeterminada",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "default": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "datos_facturacion_usuario": {
+ "name": "datos_facturacion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "datos_facturacion_usuario_id_usuario_id_fk": {
+ "name": "datos_facturacion_usuario_id_usuario_id_fk",
+ "tableFrom": "datos_facturacion",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "datos_facturacion_pais_codigo_pais_codigo_fk": {
+ "name": "datos_facturacion_pais_codigo_pais_codigo_fk",
+ "tableFrom": "datos_facturacion",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.descarga": {
+ "name": "descarga",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "bajada_en": {
+ "name": "bajada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ip": {
+ "name": "ip",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "agente": {
+ "name": "agente",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "descarga_usuario": {
+ "name": "descarga_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "descarga_fecha": {
+ "name": "descarga_fecha",
+ "columns": [
+ {
+ "expression": "bajada_en",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "descarga_usuario_id_usuario_id_fk": {
+ "name": "descarga_usuario_id_usuario_id_fk",
+ "tableFrom": "descarga",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "descarga_cancion_id_cancion_id_fk": {
+ "name": "descarga_cancion_id_cancion_id_fk",
+ "tableFrom": "descarga",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.factura": {
+ "name": "factura",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "serie": {
+ "name": "serie",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "numero": {
+ "name": "numero",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "tipo": {
+ "name": "tipo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'normal'"
+ },
+ "rectifica_a_id": {
+ "name": "rectifica_a_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "fecha": {
+ "name": "fecha",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "base_centimos": {
+ "name": "base_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "iva_tipo": {
+ "name": "iva_tipo",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "iva_cuota_centimos": {
+ "name": "iva_cuota_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_centimos": {
+ "name": "total_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "moneda": {
+ "name": "moneda",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'eur'"
+ },
+ "datos_congelados": {
+ "name": "datos_congelados",
+ "type": "jsonb",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pais_codigo": {
+ "name": "pais_codigo",
+ "type": "char(2)",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "factura_serie_numero": {
+ "name": "factura_serie_numero",
+ "columns": [
+ {
+ "expression": "serie",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "numero",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "factura_pedido": {
+ "name": "factura_pedido",
+ "columns": [
+ {
+ "expression": "pedido_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "factura_fecha": {
+ "name": "factura_fecha",
+ "columns": [
+ {
+ "expression": "fecha",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "factura_pedido_id_pedido_id_fk": {
+ "name": "factura_pedido_id_pedido_id_fk",
+ "tableFrom": "factura",
+ "tableTo": "pedido",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ },
+ "factura_pais_codigo_pais_codigo_fk": {
+ "name": "factura_pais_codigo_pais_codigo_fk",
+ "tableFrom": "factura",
+ "tableTo": "pais",
+ "columnsFrom": [
+ "pais_codigo"
+ ],
+ "columnsTo": [
+ "codigo"
+ ],
+ "onDelete": "no action",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.codigo_acceso": {
+ "name": "codigo_acceso",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "hash": {
+ "name": "hash",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "intentos": {
+ "name": "intentos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "usado_en": {
+ "name": "usado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "codigo_acceso_email": {
+ "name": "codigo_acceso_email",
+ "columns": [
+ {
+ "expression": "email",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.identidad": {
+ "name": "identidad",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "proveedor": {
+ "name": "proveedor",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sujeto": {
+ "name": "sujeto",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ultimo_acceso_en": {
+ "name": "ultimo_acceso_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "identidad_proveedor_sujeto": {
+ "name": "identidad_proveedor_sujeto",
+ "columns": [
+ {
+ "expression": "proveedor",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ },
+ {
+ "expression": "sujeto",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "identidad_usuario": {
+ "name": "identidad_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "identidad_usuario_id_usuario_id_fk": {
+ "name": "identidad_usuario_id_usuario_id_fk",
+ "tableFrom": "identidad",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.limite": {
+ "name": "limite",
+ "schema": "",
+ "columns": {
+ "clave": {
+ "name": "clave",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "intentos": {
+ "name": "intentos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "bigint",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {
+ "limite_expira": {
+ "name": "limite_expira",
+ "columns": [
+ {
+ "expression": "expira_en",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.sesion": {
+ "name": "sesion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "expira_en": {
+ "name": "expira_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "sesion_usuario": {
+ "name": "sesion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "sesion_usuario_id_usuario_id_fk": {
+ "name": "sesion_usuario_id_usuario_id_fk",
+ "tableFrom": "sesion",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.usuario": {
+ "name": "usuario",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "email": {
+ "name": "email",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "nombre": {
+ "name": "nombre",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "rol": {
+ "name": "rol",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'persona'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "ultimo_acceso_en": {
+ "name": "ultimo_acceso_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "usuario_email_unique": {
+ "name": "usuario_email_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.carrito": {
+ "name": "carrito",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizado_en": {
+ "name": "actualizado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "carrito_usuario_unico": {
+ "name": "carrito_usuario_unico",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": true,
+ "where": "\"carrito\".\"usuario_id\" is not null",
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "carrito_usuario_id_usuario_id_fk": {
+ "name": "carrito_usuario_id_usuario_id_fk",
+ "tableFrom": "carrito",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.carrito_item": {
+ "name": "carrito_item",
+ "schema": "",
+ "columns": {
+ "carrito_id": {
+ "name": "carrito_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "anadido_en": {
+ "name": "anadido_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "carrito_item_carrito_id_carrito_id_fk": {
+ "name": "carrito_item_carrito_id_carrito_id_fk",
+ "tableFrom": "carrito_item",
+ "tableTo": "carrito",
+ "columnsFrom": [
+ "carrito_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "carrito_item_cancion_id_cancion_id_fk": {
+ "name": "carrito_item_cancion_id_cancion_id_fk",
+ "tableFrom": "carrito_item",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "carrito_item_carrito_id_cancion_id_pk": {
+ "name": "carrito_item_carrito_id_cancion_id_pk",
+ "columns": [
+ "carrito_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.compra": {
+ "name": "compra",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "comprado_en": {
+ "name": "comprado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "compra_usuario_id_usuario_id_fk": {
+ "name": "compra_usuario_id_usuario_id_fk",
+ "tableFrom": "compra",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "compra_cancion_id_cancion_id_fk": {
+ "name": "compra_cancion_id_cancion_id_fk",
+ "tableFrom": "compra",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ },
+ "compra_pedido_id_pedido_id_fk": {
+ "name": "compra_pedido_id_pedido_id_fk",
+ "tableFrom": "compra",
+ "tableTo": "pedido",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "compra_usuario_id_cancion_id_pk": {
+ "name": "compra_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pedido": {
+ "name": "pedido",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "sesion_pago_id": {
+ "name": "sesion_pago_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "estado": {
+ "name": "estado",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'pendiente'"
+ },
+ "packs": {
+ "name": "packs",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "total_centimos": {
+ "name": "total_centimos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "moneda": {
+ "name": "moneda",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "'eur'"
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "pagado_en": {
+ "name": "pagado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": false
+ }
+ },
+ "indexes": {
+ "pedido_usuario": {
+ "name": "pedido_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "pedido_usuario_id_usuario_id_fk": {
+ "name": "pedido_usuario_id_usuario_id_fk",
+ "tableFrom": "pedido",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {
+ "pedido_sesion_pago_id_unique": {
+ "name": "pedido_sesion_pago_id_unique",
+ "nullsNotDistinct": false,
+ "columns": [
+ "sesion_pago_id"
+ ]
+ }
+ },
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.pedido_item": {
+ "name": "pedido_item",
+ "schema": "",
+ "columns": {
+ "pedido_id": {
+ "name": "pedido_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "titulo": {
+ "name": "titulo",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {
+ "pedido_item_pedido_id_pedido_id_fk": {
+ "name": "pedido_item_pedido_id_pedido_id_fk",
+ "tableFrom": "pedido_item",
+ "tableTo": "pedido",
+ "columnsFrom": [
+ "pedido_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "pedido_item_cancion_id_cancion_id_fk": {
+ "name": "pedido_item_cancion_id_cancion_id_fk",
+ "tableFrom": "pedido_item",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "restrict",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "pedido_item_pedido_id_cancion_id_pk": {
+ "name": "pedido_item_pedido_id_cancion_id_pk",
+ "columns": [
+ "pedido_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.favorito": {
+ "name": "favorito",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "marcado_en": {
+ "name": "marcado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_favorito_usuario": {
+ "name": "idx_favorito_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "favorito_usuario_id_usuario_id_fk": {
+ "name": "favorito_usuario_id_usuario_id_fk",
+ "tableFrom": "favorito",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "favorito_cancion_id_cancion_id_fk": {
+ "name": "favorito_cancion_id_cancion_id_fk",
+ "tableFrom": "favorito",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "favorito_usuario_id_cancion_id_pk": {
+ "name": "favorito_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.reproduccion": {
+ "name": "reproduccion",
+ "schema": "",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "text",
+ "primaryKey": true,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false
+ },
+ "segundos": {
+ "name": "segundos",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true,
+ "default": 0
+ },
+ "dia": {
+ "name": "dia",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creado_en": {
+ "name": "creado_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "reproduccion_dia": {
+ "name": "reproduccion_dia",
+ "columns": [
+ {
+ "expression": "dia",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "reproduccion_cancion": {
+ "name": "reproduccion_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ },
+ "reproduccion_usuario": {
+ "name": "reproduccion_usuario",
+ "columns": [
+ {
+ "expression": "usuario_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "reproduccion_cancion_id_cancion_id_fk": {
+ "name": "reproduccion_cancion_id_cancion_id_fk",
+ "tableFrom": "reproduccion",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "reproduccion_usuario_id_usuario_id_fk": {
+ "name": "reproduccion_usuario_id_usuario_id_fk",
+ "tableFrom": "reproduccion",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "set null",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {},
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ },
+ "public.valoracion": {
+ "name": "valoracion",
+ "schema": "",
+ "columns": {
+ "usuario_id": {
+ "name": "usuario_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "cancion_id": {
+ "name": "cancion_id",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "puntuacion": {
+ "name": "puntuacion",
+ "type": "integer",
+ "primaryKey": false,
+ "notNull": true
+ },
+ "creada_en": {
+ "name": "creada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ },
+ "actualizada_en": {
+ "name": "actualizada_en",
+ "type": "timestamp with time zone",
+ "primaryKey": false,
+ "notNull": true,
+ "default": "now()"
+ }
+ },
+ "indexes": {
+ "idx_valoracion_cancion": {
+ "name": "idx_valoracion_cancion",
+ "columns": [
+ {
+ "expression": "cancion_id",
+ "isExpression": false,
+ "asc": true,
+ "nulls": "last"
+ }
+ ],
+ "isUnique": false,
+ "concurrently": false,
+ "method": "btree",
+ "with": {}
+ }
+ },
+ "foreignKeys": {
+ "valoracion_usuario_id_usuario_id_fk": {
+ "name": "valoracion_usuario_id_usuario_id_fk",
+ "tableFrom": "valoracion",
+ "tableTo": "usuario",
+ "columnsFrom": [
+ "usuario_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ },
+ "valoracion_cancion_id_cancion_id_fk": {
+ "name": "valoracion_cancion_id_cancion_id_fk",
+ "tableFrom": "valoracion",
+ "tableTo": "cancion",
+ "columnsFrom": [
+ "cancion_id"
+ ],
+ "columnsTo": [
+ "id"
+ ],
+ "onDelete": "cascade",
+ "onUpdate": "no action"
+ }
+ },
+ "compositePrimaryKeys": {
+ "valoracion_usuario_id_cancion_id_pk": {
+ "name": "valoracion_usuario_id_cancion_id_pk",
+ "columns": [
+ "usuario_id",
+ "cancion_id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "policies": {},
+ "checkConstraints": {},
+ "isRLSEnabled": false
+ }
+ },
+ "enums": {},
+ "schemas": {},
+ "sequences": {
+ "public.artista_codigo_seq": {
+ "name": "artista_codigo_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "9223372036854775807",
+ "cache": "1",
+ "cycle": false
+ },
+ "public.cancion_codigo_seq": {
+ "name": "cancion_codigo_seq",
+ "schema": "public",
+ "increment": "1",
+ "startWith": "1",
+ "minValue": "1",
+ "maxValue": "9223372036854775807",
+ "cache": "1",
+ "cycle": false
+ }
+ },
+ "roles": {},
+ "policies": {},
+ "views": {},
+ "_meta": {
+ "columns": {},
+ "schemas": {},
+ "tables": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json
index baaf1cd..f9f52e7 100644
--- a/drizzle/meta/_journal.json
+++ b/drizzle/meta/_journal.json
@@ -78,6 +78,55 @@
"when": 1788898884661,
"tag": "0010_texto_de_estilos_y_discos",
"breakpoints": true
+ },
+ {
+ "idx": 11,
+ "version": "7",
+ "when": 1788949140000,
+ "tag": "0011_administradores",
+ "breakpoints": true
+ },
+ {
+ "idx": 12,
+ "version": "7",
+ "when": 1788965520000,
+ "tag": "0012_prompts_de_una_cancion",
+ "breakpoints": true
+ },
+ {
+ "idx": 13,
+ "version": "7",
+ "when": 1789041720000,
+ "tag": "0013_integridad_concurrente",
+ "breakpoints": true
+ },
+ {
+ "idx": 14,
+ "version": "7",
+ "when": 1789042140000,
+ "tag": "0014_artistas_y_audio",
+ "breakpoints": true
+ },
+ {
+ "idx": 15,
+ "version": "7",
+ "when": 1789042620000,
+ "tag": "0015_condiciones_escucha_completa",
+ "breakpoints": true
+ },
+ {
+ "idx": 16,
+ "version": "7",
+ "when": 1789053311680,
+ "tag": "0016_sincronizar_migraciones_manuales",
+ "breakpoints": true
+ },
+ {
+ "idx": 17,
+ "version": "7",
+ "when": 1789053373570,
+ "tag": "0017_verificar_sincronizacion",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/package.json b/package.json
index e3bc6ab..f670612 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,8 @@
"db:push": "drizzle-kit push",
"db:generate": "drizzle-kit generate",
"db:migrate": "node --env-file=.env scripts/db/migrar.mjs",
+ "db:migrate:check": "node --env-file=.env scripts/db/comprobar-migraciones.mjs",
+ "db:auditar-musica": "node --env-file=.env scripts/db/auditar-dominio-musical.mjs",
"db:studio": "drizzle-kit studio",
"medios": "node scripts/medios.mjs",
"predev": "node scripts/medios.mjs",
diff --git a/scripts/config/audio.mjs b/scripts/config/audio.mjs
new file mode 100644
index 0000000..a9edd55
--- /dev/null
+++ b/scripts/config/audio.mjs
@@ -0,0 +1,7 @@
+/** Perfil único de derivados públicos; cambiarlo obliga a regenerarlos. */
+export const PERFIL_ESCUCHA = Object.freeze({
+ id: 'mp3-96-v1',
+ formato: 'mp3',
+ codecFfmpeg: 'libmp3lame',
+ bitrateKbps: 96
+});
diff --git a/scripts/db/auditar-dominio-musical.mjs b/scripts/db/auditar-dominio-musical.mjs
new file mode 100644
index 0000000..593b0e0
--- /dev/null
+++ b/scripts/db/auditar-dominio-musical.mjs
@@ -0,0 +1,50 @@
+/** Informe de paridad tras migrar artistas, versiones y representaciones. */
+
+import pg from 'pg';
+
+const cliente = new pg.Client({
+ connectionString: process.env.DATABASE_URL,
+ query_timeout: 30_000
+});
+await cliente.connect();
+
+const {
+ rows: [n]
+} = await cliente.query(`
+ select
+ (select count(*) from cancion where version_de_id is null)::int as canciones,
+ (select count(*) from cancion where version_de_id is not null)::int as versiones,
+ (select count(*) from cancion where codigo is null)::int as canciones_sin_codigo,
+ (select count(*) from artista)::int as artistas,
+ (select count(*) from cancion_persona where rol = 'interprete')::int as creditos_anteriores,
+ (select count(*) from cancion_interprete)::int as creditos_nuevos,
+ (select count(*) from cancion_audio where uso = 'master')::int as masters,
+ (select count(*) from cancion_audio where uso = 'stream')::int as streams,
+ (select count(*) from cancion c where c.estado = 'publicado'
+ and not exists (select 1 from cancion_audio ca where ca.cancion_id = c.id and ca.uso = 'stream'))::int
+ as publicadas_sin_stream
+`);
+
+const { rows: problemas } = await cliente.query(`
+ select 'intérprete sin migrar' as tipo, c.slug as referencia
+ from cancion_persona cp
+ join cancion c on c.id = cp.cancion_id
+ where cp.rol = 'interprete'
+ and not exists (select 1 from cancion_interprete ci where ci.cancion_id = cp.cancion_id)
+ union all
+ select 'artista sin código', slug from artista where codigo is null or btrim(codigo) = ''
+ union all
+ select 'versión sin código', slug from cancion
+ where version_de_id is not null and (version_codigo is null or btrim(version_codigo) = '')
+ order by tipo, referencia
+`);
+
+console.table(n);
+if (problemas.length) console.table(problemas);
+await cliente.end();
+
+if (problemas.length || n.canciones_sin_codigo || n.publicadas_sin_stream) {
+ console.error('La migración todavía no cumple la paridad requerida.');
+ process.exit(1);
+}
+console.log('Dominio musical íntegro: códigos, créditos y streams completos.');
diff --git a/scripts/db/comprobar-migraciones.mjs b/scripts/db/comprobar-migraciones.mjs
new file mode 100644
index 0000000..e965489
--- /dev/null
+++ b/scripts/db/comprobar-migraciones.mjs
@@ -0,0 +1,42 @@
+/** Ejecuta migraciones dentro de una transacción que siempre se revierte. */
+
+import fs from 'node:fs';
+import path from 'node:path';
+import pg from 'pg';
+
+const nombres = process.argv.slice(2);
+if (nombres.length === 0)
+ throw new Error('Indica al menos una migración, por ejemplo 0014_artistas_y_audio.sql.');
+
+const sentenciasDe = (texto) =>
+ texto
+ .split('--> statement-breakpoint')
+ .map((s) => s.trim())
+ .filter((s) => s && s.split('\n').some((l) => l.trim() && !l.trim().startsWith('--')));
+
+const cliente = new pg.Client({
+ connectionString: process.env.DATABASE_URL,
+ query_timeout: 120_000
+});
+await cliente.connect();
+await cliente.query('BEGIN');
+
+try {
+ for (const nombre of nombres) {
+ const ruta = path.join('drizzle', nombre);
+ const sentencias = sentenciasDe(fs.readFileSync(ruta, 'utf8'));
+ for (const [indice, sentencia] of sentencias.entries()) {
+ try {
+ await cliente.query(sentencia);
+ } catch (error) {
+ throw new Error(`${nombre}, sentencia ${indice + 1}: ${error.message}`, { cause: error });
+ }
+ }
+ console.log(` ${nombre}: ${sentencias.length} sentencias válidas`);
+ }
+} finally {
+ await cliente.query('ROLLBACK').catch(() => {});
+ await cliente.end();
+}
+
+console.log('Comprobadas y revertidas: la base no ha cambiado.');
diff --git a/scripts/db/volcar-medios.mjs b/scripts/db/volcar-medios.mjs
index 4df2fca..67f3fdb 100644
--- a/scripts/db/volcar-medios.mjs
+++ b/scripts/db/volcar-medios.mjs
@@ -1,6 +1,6 @@
/**
- * Vuelca los archivos —audio, muestras y portadas— a la tabla `medio` y los
- * enlaza con quien los usa.
+ * Vuelca másteres, copias completas de escucha, muestras antiguas y portadas a
+ * `medio`, y reconstruye sus relaciones.
*
* npm run db:medios
* npm run db:medios -- --seco
@@ -20,20 +20,45 @@ import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import pg from 'pg';
+import { load as leerYaml } from 'js-yaml';
+import { PERFIL_ESCUCHA } from '../config/audio.mjs';
const SECO = process.argv.includes('--seco');
/** Dónde vive cada clase de archivo y si se puede pedir por URL. */
const ALMACENES = [
- { clase: 'audio', raiz: 'media/audio', publico: false, carpeta: 'audio', prefijo: '' },
{
+ nombre: 'máster',
+ clase: 'audio',
+ raiz: 'media/audio',
+ publico: false,
+ carpeta: 'audio',
+ prefijo: ''
+ },
+ {
+ nombre: 'escucha',
+ clase: 'audio',
+ raiz: 'static/escucha',
+ publico: true,
+ carpeta: 'escucha',
+ prefijo: '/escucha/'
+ },
+ {
+ nombre: 'muestra',
clase: 'muestra',
raiz: 'static/muestras',
publico: true,
carpeta: 'muestras',
prefijo: '/muestras/'
},
- { clase: 'imagen', raiz: 'static/images', publico: true, carpeta: 'images', prefijo: '/images/' }
+ {
+ nombre: 'imagen',
+ clase: 'imagen',
+ raiz: 'static/images',
+ publico: true,
+ carpeta: 'images',
+ prefijo: '/images/'
+ }
];
const MIMES = {
@@ -57,23 +82,50 @@ function recorrer(dir) {
});
}
+const aSlug = (texto) =>
+ String(texto ?? '')
+ .normalize('NFD')
+ .replace(/\p{Diacritic}/gu, '')
+ .toLowerCase()
+ .replace(/[^a-z0-9]+/g, '-')
+ .replace(/^-+|-+$/g, '');
+
/**
* Duración en segundos, medida con ffprobe.
*
* Medida y no escrita: es el dato que más fácil se queda viejo. Si ffprobe no
* está, se deja en nulo y se avisa; no se inventa.
*/
-function duracionDe(ruta) {
+function datosDeAudio(ruta) {
try {
const salida = execFileSync(
'ffprobe',
- ['-v', 'error', '-show_entries', 'format=duration', '-of', 'csv=p=0', ruta],
+ [
+ '-v',
+ 'error',
+ '-select_streams',
+ 'a:0',
+ '-show_entries',
+ 'format=duration,bit_rate:stream=sample_rate,channels',
+ '-of',
+ 'json',
+ ruta
+ ],
{ encoding: 'utf8', timeout: 20_000 }
);
- const segundos = Number.parseFloat(salida.trim());
- return Number.isFinite(segundos) ? Math.round(segundos) : null;
+ const datos = JSON.parse(salida);
+ const segundos = Number.parseFloat(datos.format?.duration);
+ const bitrate = Number.parseInt(datos.format?.bit_rate, 10);
+ const frecuencia = Number.parseInt(datos.streams?.[0]?.sample_rate, 10);
+ const canales = Number.parseInt(datos.streams?.[0]?.channels, 10);
+ return {
+ duracionS: Number.isFinite(segundos) ? Math.round(segundos) : null,
+ bitrateKbps: Number.isFinite(bitrate) ? Math.round(bitrate / 1000) : null,
+ frecuenciaHz: Number.isFinite(frecuencia) ? frecuencia : null,
+ canales: Number.isFinite(canales) ? canales : null
+ };
} catch {
- return null;
+ return { duracionS: null, bitrateKbps: null, frecuenciaHz: null, canales: null };
}
}
@@ -114,8 +166,12 @@ for (const almacen of ALMACENES) {
const contenido = fs.readFileSync(ruta);
const relativa = path.relative(almacen.raiz, ruta).split(path.sep).join('/');
const esImagen = mime.startsWith('image/');
+ const audio = esImagen
+ ? { duracionS: null, bitrateKbps: null, frecuenciaHz: null, canales: null }
+ : datosDeAudio(ruta);
encontrados.push({
+ almacen: almacen.nombre,
clase: almacen.clase,
// La clave lleva el almacen delante: `singles/dorina.mp3` existe en audio
// y en muestras, y sin el prefijo serian la misma fila. Ademas es la ruta
@@ -126,7 +182,7 @@ for (const almacen of ALMACENES) {
mime,
bytes: contenido.length,
sha256: createHash('sha256').update(contenido).digest('hex'),
- duracionS: esImagen ? null : duracionDe(ruta),
+ ...audio,
...(esImagen ? medidasDe(ruta) : { ancho: null, alto: null })
});
}
@@ -134,10 +190,10 @@ for (const almacen of ALMACENES) {
console.log(`Encontrados ${encontrados.length} archivos\n`);
for (const almacen of ALMACENES) {
- const suyos = encontrados.filter((m) => m.clase === almacen.clase);
+ const suyos = encontrados.filter((m) => m.almacen === almacen.nombre);
const pesan = suyos.reduce((n, m) => n + m.bytes, 0);
console.log(
- ` ${almacen.clase.padEnd(9)} ${String(suyos.length).padStart(3)} archivos · ${(pesan / 1048576).toFixed(1)} MB`
+ ` ${almacen.nombre.padEnd(9)} ${String(suyos.length).padStart(3)} archivos · ${(pesan / 1048576).toFixed(1)} MB`
);
}
@@ -170,28 +226,30 @@ await c.connect();
await c.query('BEGIN');
try {
- /*
- * Se sueltan los enlaces antes de vaciar la tabla. Las columnas son
- * `ON DELETE set null`, así que Postgres lo haría solo, pero decirlo aquí
- * deja claro que el volcado no pierde nada: lo que se rehace es la fila del
- * archivo, no la canción.
- */
- await c.query('UPDATE cancion SET audio_id = NULL, muestra_id = NULL, portada_id = NULL');
- await c.query('UPDATE album SET portada_id = NULL');
- await c.query('DELETE FROM medio');
-
const idPorClave = new Map();
+ const medioPorClave = new Map();
for (const m of encontrados) {
const id = crypto.randomUUID();
- await c.query(
+ const { rows } = await c.query(
`INSERT INTO medio (id, clase, clave, publico, mime, bytes, duracion_s, ancho, alto, sha256)
- VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)`,
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
+ ON CONFLICT (clave) DO UPDATE SET
+ clase = excluded.clase,
+ publico = excluded.publico,
+ mime = excluded.mime,
+ bytes = excluded.bytes,
+ duracion_s = excluded.duracion_s,
+ ancho = excluded.ancho,
+ alto = excluded.alto,
+ sha256 = excluded.sha256
+ RETURNING id`,
[id, m.clase, m.clave, m.publico, m.mime, m.bytes, m.duracionS, m.ancho, m.alto, m.sha256]
);
- idPorClave.set(`${m.clase}:${m.clave}`, id);
- if (m.clase === 'imagen') idPorClave.set(`url:${m.url}`, id);
+ idPorClave.set(`${m.clase}:${m.clave}`, rows[0].id);
+ medioPorClave.set(`${m.clase}:${m.clave}`, m);
+ if (m.clase === 'imagen') idPorClave.set(`url:${m.url}`, rows[0].id);
}
- console.log(`\n ${encontrados.length} filas en medio`);
+ console.log(`\n ${encontrados.length} medios insertados o actualizados`);
/* --- Enlazar con lo que los usa ---------------------------------------
*
@@ -199,7 +257,7 @@ try {
* volcado del catálogo no guardó esas rutas: guardarlas como texto habría
* sido repetir el problema que esta tabla viene a resolver.
*/
- const enlazados = { audio: 0, muestra: 0, portadaCancion: 0, portadaAlbum: 0 };
+ const enlazados = { master: 0, stream: 0, muestra: 0, portadaCancion: 0, portadaAlbum: 0 };
const huerfanos = [];
const canciones = fs
@@ -211,22 +269,81 @@ try {
}));
for (const { slug, texto } of canciones) {
- const audio = /^audio:\s*(.+)$/m
- .exec(texto)?.[1]
- .trim()
- .replace(/^['"]|['"]$/g, '');
+ const cabecera = /^---\r?\n([\s\S]*?)\r?\n---/.exec(texto)?.[1];
+ const datos = cabecera ? (leerYaml(cabecera) ?? {}) : {};
const portada = /^portada:\s*(.+)$/m
.exec(texto)?.[1]
.trim()
.replace(/^['"]|['"]$/g, '');
- if (audio) {
+ const audios = [
+ { slug, audio: datos.audio },
+ ...(Array.isArray(datos.versiones)
+ ? datos.versiones.map((version) => ({
+ slug: `${slug}-${version.id ?? aSlug(version.nombre)}`,
+ audio: version.audio
+ }))
+ : [])
+ ];
+
+ for (const entidad of audios) {
+ const { rows: destinos } = await c.query('SELECT id FROM cancion WHERE slug = $1', [
+ entidad.slug
+ ]);
+ if (destinos.length === 0) {
+ huerfanos.push(`${entidad.slug}: la canción no existe en la base`);
+ continue;
+ }
+ await c.query('DELETE FROM cancion_audio WHERE cancion_id = $1', [destinos[0].id]);
+ await c.query('UPDATE cancion SET audio_id = NULL, muestra_id = NULL WHERE id = $1', [
+ destinos[0].id
+ ]);
+ const audio =
+ typeof entidad.audio === 'string' ? entidad.audio.replace(/^\//, '') : undefined;
+ if (!audio) continue;
const id = idPorClave.get(`audio:audio/${audio}`);
if (id) {
- await c.query('UPDATE cancion SET audio_id = $1 WHERE slug = $2', [id, slug]);
- enlazados.audio++;
+ const master = medioPorClave.get(`audio:audio/${audio}`);
+ await c.query('UPDATE cancion SET audio_id = $1 WHERE slug = $2', [id, entidad.slug]);
+ await c.query(
+ `INSERT INTO cancion_audio
+ (cancion_id, medio_id, uso, formato, bitrate_kbps, frecuencia_hz, canales)
+ SELECT id, $1, 'master', $2, $3, $4, $5 FROM cancion WHERE slug = $6
+ ON CONFLICT DO NOTHING`,
+ [
+ id,
+ path.extname(audio).slice(1).toLowerCase() || 'audio',
+ master?.bitrateKbps ?? null,
+ master?.frecuenciaHz ?? null,
+ master?.canales ?? null,
+ entidad.slug
+ ]
+ );
+ enlazados.master++;
+ } else {
+ huerfanos.push(`${entidad.slug}: el audio ${audio} no existe`);
+ }
+
+ const escucha = audio.replace(/\.[^.]+$/, '.mp3');
+ const idEscucha = idPorClave.get(`audio:escucha/${escucha}`);
+ if (idEscucha) {
+ const stream = medioPorClave.get(`audio:escucha/${escucha}`);
+ await c.query(
+ `INSERT INTO cancion_audio
+ (cancion_id, medio_id, uso, formato, bitrate_kbps, frecuencia_hz, canales)
+ SELECT id, $1, 'stream', 'mp3', $2, $3, $4 FROM cancion WHERE slug = $5
+ ON CONFLICT DO NOTHING`,
+ [
+ idEscucha,
+ stream?.bitrateKbps ?? PERFIL_ESCUCHA.bitrateKbps,
+ stream?.frecuenciaHz ?? null,
+ stream?.canales ?? null,
+ entidad.slug
+ ]
+ );
+ enlazados.stream++;
} else {
- huerfanos.push(`${slug}: el audio ${audio} no existe`);
+ huerfanos.push(`${entidad.slug}: falta la escucha completa ${escucha}`);
}
/*
@@ -237,11 +354,15 @@ try {
const muestra = audio.replace(/\.[^.]+$/, '.mp3');
const idMuestra = idPorClave.get(`muestra:muestras/${muestra}`);
if (idMuestra) {
- await c.query('UPDATE cancion SET muestra_id = $1 WHERE slug = $2', [idMuestra, slug]);
+ await c.query('UPDATE cancion SET muestra_id = $1 WHERE slug = $2', [
+ idMuestra,
+ entidad.slug
+ ]);
enlazados.muestra++;
}
}
+ await c.query('UPDATE cancion SET portada_id = NULL WHERE slug = $1', [slug]);
if (portada) {
const id = idPorClave.get(`url:${portada}`);
if (id) {
@@ -260,6 +381,7 @@ try {
.exec(texto)?.[1]
.trim()
.replace(/^['"]|['"]$/g, '');
+ await c.query('UPDATE album SET portada_id = NULL WHERE slug = $1', [slug]);
if (!portada) continue;
const id = idPorClave.get(`url:${portada}`);
@@ -272,7 +394,7 @@ try {
}
console.log(
- ` enlazados: ${enlazados.audio} audios, ${enlazados.muestra} muestras, ` +
+ ` enlazados: ${enlazados.master} másteres, ${enlazados.stream} escuchas, ${enlazados.muestra} muestras antiguas, ` +
`${enlazados.portadaCancion} portadas de tema, ${enlazados.portadaAlbum} de disco`
);
diff --git a/scripts/db/volcar.mjs b/scripts/db/volcar.mjs
index d7a6240..d510c0f 100644
--- a/scripts/db/volcar.mjs
+++ b/scripts/db/volcar.mjs
@@ -102,6 +102,16 @@ const slugificar = (nombre) =>
async function volcar(c, contenido, informe) {
const { estilos, albumes, canciones, capitulos, entradas, legales, paginas } = contenido;
+ const { rows: actividad } = await c.query(`
+ select
+ (select count(*) from compra)::int as compras,
+ (select count(*) from pedido_item)::int as lineas_pedido
+ `);
+ if (actividad[0].compras > 0 || actividad[0].lineas_pedido > 0) {
+ throw new Error(
+ 'El volcado total es solo para una base vacía: ya hay compras o pedidos. Usa el panel y migraciones aditivas.'
+ );
+ }
/* --- Se borra lo volcado antes de reescribirlo -----------------------
*
@@ -132,6 +142,8 @@ async function volcar(c, contenido, informe) {
'pagina',
'autoria',
'registro_obra',
+ 'cancion_audio',
+ 'cancion_interprete',
'cancion_persona',
'cancion_enlace',
'cancion_etiqueta',
@@ -143,6 +155,9 @@ async function volcar(c, contenido, informe) {
'album',
'etiqueta',
'estilo',
+ 'artista_identificador',
+ 'artista_persona',
+ 'artista',
'persona'
];
for (const tabla of aVaciar) await c.query(`DELETE FROM "${tabla}"`);
@@ -168,6 +183,30 @@ async function volcar(c, contenido, informe) {
return id;
};
+ /* Identidad pública: separada de la persona física que firma la obra. */
+ const artistas = new Map();
+ const artista = async (nombre, personaId) => {
+ const limpio = nombre.trim();
+ if (artistas.has(limpio)) return artistas.get(limpio);
+ const id = nuevoId();
+ const tipo =
+ limpio === 'Los del Puerto' ? 'grupo' : limpio === 'Senza Paura' ? 'proyecto' : 'persona';
+ await c.query(
+ `INSERT INTO artista (id, slug, tipo, nombre, estado)
+ VALUES ($1,$2,$3,$4,'publicado')`,
+ [id, slugificar(limpio), tipo, limpio]
+ );
+ if (tipo === 'persona') {
+ await c.query(
+ `INSERT INTO artista_persona (artista_id, persona_id, relacion)
+ VALUES ($1,$2,'identidad')`,
+ [id, personaId]
+ );
+ }
+ artistas.set(limpio, id);
+ return id;
+ };
+
/* --- Etiquetas ------------------------------------------------------- */
const etiquetas = new Map();
const etiqueta = async (nombre) => {
@@ -267,7 +306,7 @@ async function volcar(c, contenido, informe) {
for (const [rol, nombres] of [
['letra', datos.letra],
['musica', datos.musica],
- ['interprete', datos.interpretes]
+ ['interprete', datos.interpretes.map((interprete) => interprete.nombre)]
]) {
for (const [i, nombre] of (nombres ?? []).entries()) {
await c.query(
@@ -277,6 +316,15 @@ async function volcar(c, contenido, informe) {
);
}
}
+ for (const [i, interprete] of datos.interpretes.entries()) {
+ const personaId = await persona(interprete.nombre);
+ const artistaId = await artista(interprete.nombre, personaId);
+ await c.query(
+ `INSERT INTO cancion_interprete (cancion_id, artista_id, rol, acreditado_como, orden)
+ VALUES ($1,$2,$3,$4,$5)`,
+ [id, artistaId, interprete.rol, interprete.nombre, i]
+ );
+ }
for (const nombre of datos.etiquetas ?? []) {
await c.query(
@@ -338,17 +386,19 @@ async function volcar(c, contenido, informe) {
* «no lo sé» o «lo mismo de arriba».
*/
for (const [i, v] of (datos.versiones ?? []).entries()) {
+ const versionId = nuevoId();
await c.query(
`INSERT INTO cancion (id, slug, titulo, estilo_id, version_de_id, version_nombre,
- version_orden, duracion_s, ano, letra, idioma, instrumental, estado)
- VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,'publicado')`,
+ version_codigo, version_orden, duracion_s, ano, letra, idioma, instrumental, estado)
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,'publicado')`,
[
- nuevoId(),
+ versionId,
`${datos.slug}-${v.id}`,
datos.titulo,
idEstilo.get(datos.estilo),
id,
v.nombre,
+ v.id,
i,
v.duracion ?? null,
datos.ano ?? null,
@@ -357,6 +407,15 @@ async function volcar(c, contenido, informe) {
datos.instrumental
]
);
+ for (const [orden, interprete] of datos.interpretes.entries()) {
+ const personaId = await persona(interprete.nombre);
+ const artistaId = await artista(interprete.nombre, personaId);
+ await c.query(
+ `INSERT INTO cancion_interprete (cancion_id, artista_id, rol, acreditado_como, orden)
+ VALUES ($1,$2,$3,$4,$5)`,
+ [versionId, artistaId, interprete.rol, interprete.nombre, orden]
+ );
+ }
versiones++;
}
}
diff --git a/scripts/medios.mjs b/scripts/medios.mjs
index 142119f..ba70217 100644
--- a/scripts/medios.mjs
+++ b/scripts/medios.mjs
@@ -3,17 +3,16 @@
* puede preparar.
*
* El panel de contenido escribe archivos en el repositorio, así que subir el
- * máster desde ahí es fácil. Lo que no puede hacer es recortar el fragmento de
- * muestra ni medir la duración: eso es ffmpeg, y ffmpeg no corre dentro de una
- * pestaña. Este script cierra ese hueco.
+ * máster desde ahí es fácil. Lo que no puede hacer es generar la copia pública
+ * completa de menor calidad ni medir la duración: eso es ffmpeg.
*
* Qué hace, por cada canción de `src/content/canciones/`:
*
* 1. Si su clave de audio apunta a la bandeja (`subidas/…`), mueve el archivo
* a la carpeta que le toca —la del disco, o `singles/`— con el nombre de
* la convención, y reescribe la clave en el Markdown.
- * 2. Si falta el fragmento de muestra, o es más viejo que el máster, lo
- * genera.
+ * 2. Si falta la copia completa de escucha, o es más vieja que el máster, la
+ * genera a 96 kbps.
* 3. Si no tiene duración escrita, la mide y la escribe.
*
* Corre solo antes de `npm run dev` y de `npm run build`, así que subir un tema
@@ -21,7 +20,8 @@
* `npm run medios`.
*
* Sin ffmpeg no falla: avisa de lo que no ha podido hacer y sigue. Un entorno
- * de despliegue no lo necesita, porque las muestras van en el repositorio.
+ * de despliegue no lo necesita, porque las copias de escucha van en el
+ * repositorio.
*/
import { spawnSync } from 'node:child_process';
@@ -29,17 +29,17 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { load as leerYaml } from 'js-yaml';
+import { PERFIL_ESCUCHA } from './config/audio.mjs';
const RAIZ = path.resolve(import.meta.dirname, '..');
const CANCIONES = path.join(RAIZ, 'src/content/canciones');
const MASTERS = path.join(RAIZ, 'media/audio');
-const MUESTRAS = path.join(RAIZ, 'static/muestras');
+const ESCUCHAS = path.join(RAIZ, 'static/escucha');
/** Carpeta donde deja el panel lo que se sube; nada se queda aquí. */
const BANDEJA = 'subidas';
-/** Fragmento de muestra: 40 s desde el segundo 30, con 4 s de fundido final. */
-const MUESTRA = { desde: 30, dura: 40, fundido: 4 };
+/** Perfil audible pero claramente inferior al archivo entregado al comprar. */
const avisos = [];
const hechos = [];
@@ -121,64 +121,57 @@ function colocar(claveVieja, claveNueva) {
return true;
}
-/**
- * Los argumentos del recorte.
- *
- * `-ss` va **antes** de `-i`, y eso no es cosmético. Detrás de `-i` el corte se
- * hace a la salida, pero el filtro sigue viendo los tiempos del original: un
- * `afade` en el segundo 36 se aplicaría en el 36 de la canción, es decir a los
- * seis de empezar el fragmento, y el resto saldría mudo. Delante de `-i` los
- * tiempos se reinician en cero y el fundido cae donde debe.
- */
-export function argumentosDeMuestra(master, muestra, desde, dura) {
- const fundido = Math.max(0, dura - MUESTRA.fundido);
+/** Nombre equivalente de la copia pública: siempre MP3. */
+export function claveDeEscucha(clave) {
+ return clave.replace(/\.[^.]+$/, '') + '.mp3';
+}
+
+/** Argumentos deterministas de la transcodificación completa de escucha. */
+export function argumentosDeEscucha(master, escucha) {
return [
'-v',
'error',
'-y',
- '-ss',
- String(desde),
- '-t',
- String(dura),
'-i',
master,
- '-af',
- `afade=t=out:st=${fundido}:d=${MUESTRA.fundido}`,
- muestra
+ '-vn',
+ '-map_metadata',
+ '-1',
+ '-codec:a',
+ PERFIL_ESCUCHA.codecFfmpeg,
+ '-b:a',
+ `${PERFIL_ESCUCHA.bitrateKbps}k`,
+ escucha
];
}
-/** Recorta el fragmento público si falta o si el máster es más nuevo. */
-function generarMuestra(clave) {
+/** Genera la canción pública completa si falta o si el máster es más nuevo. */
+function generarEscucha(clave) {
const master = path.join(MASTERS, clave);
- const muestra = path.join(MUESTRAS, clave);
+ const escucha = path.join(ESCUCHAS, claveDeEscucha(clave));
if (!fs.existsSync(master)) {
- avisos.push(`${clave}: no hay máster en media/audio/, no se puede generar la muestra.`);
+ avisos.push(`${clave}: no hay máster en media/audio/, no se puede generar la escucha.`);
return;
}
- if (fs.existsSync(muestra) && fs.statSync(muestra).mtimeMs >= fs.statSync(master).mtimeMs) {
+ if (fs.existsSync(escucha) && fs.statSync(escucha).mtimeMs >= fs.statSync(master).mtimeMs) {
return;
}
if (!hayFfmpeg) {
- avisos.push(`${clave}: falta el fragmento de muestra y no hay ffmpeg para generarlo.`);
+ avisos.push(`${clave}: falta la copia de escucha y no hay ffmpeg para generarla.`);
return;
}
- // Un tema corto no da para empezar en el segundo 30: se recorta desde el
- // principio y se toma lo que haya, para que la muestra no salga vacía.
- const total = medir(master) ?? 0;
- const desde = total > MUESTRA.desde + MUESTRA.dura ? MUESTRA.desde : 0;
- const dura = Math.min(MUESTRA.dura, Math.max(1, total - desde));
-
- fs.mkdirSync(path.dirname(muestra), { recursive: true });
- const hecho = ejecutar('ffmpeg', argumentosDeMuestra(master, muestra, desde, dura));
+ fs.mkdirSync(path.dirname(escucha), { recursive: true });
+ const hecho = ejecutar('ffmpeg', argumentosDeEscucha(master, escucha));
if (hecho === undefined) {
- avisos.push(`${clave}: ffmpeg no pudo generar la muestra.`);
+ avisos.push(`${clave}: ffmpeg no pudo generar la escucha completa.`);
return;
}
- hechos.push(`muestra ${clave} (${dura} s desde ${desde})`);
+ hechos.push(
+ `escucha ${claveDeEscucha(clave)} (${PERFIL_ESCUCHA.bitrateKbps} kbps, ${PERFIL_ESCUCHA.id})`
+ );
}
/**
@@ -228,7 +221,7 @@ function procesar(archivo) {
}
}
- generarMuestra(clave);
+ generarEscucha(clave);
if (!datos.duracion && hayFfmpeg) {
const segundos = medir(path.join(MASTERS, clave));
@@ -257,7 +250,7 @@ function procesar(archivo) {
}
}
- generarMuestra(clave);
+ generarEscucha(clave);
}
if (tocado) {
diff --git a/scripts/medios.spec.mjs b/scripts/medios.spec.mjs
index 425e0b6..259b599 100644
--- a/scripts/medios.spec.mjs
+++ b/scripts/medios.spec.mjs
@@ -1,5 +1,12 @@
import { describe, expect, it } from 'vitest';
-import { argumentosDeMuestra, aSlug, claveCanonica, comoDuracion, enLaBandeja } from './medios.mjs';
+import {
+ argumentosDeEscucha,
+ aSlug,
+ claveCanonica,
+ claveDeEscucha,
+ comoDuracion,
+ enLaBandeja
+} from './medios.mjs';
describe('claveCanonica', () => {
it('agrupa por disco y numera como la pista', () => {
@@ -68,34 +75,20 @@ describe('aSlug', () => {
});
});
-describe('argumentosDeMuestra', () => {
- const args = argumentosDeMuestra(
- 'media/audio/singles/dorina.mp3',
- 'static/muestras/singles/dorina.mp3',
- 30,
- 40
- );
-
- it('corta a la entrada, no a la salida', () => {
- // Con `-ss` detrás de `-i` el filtro sigue viendo los tiempos del
- // original: el fundido cae seis segundos después de empezar y el resto
- // del fragmento sale mudo. Pasó de verdad.
- expect(args.indexOf('-ss')).toBeLessThan(args.indexOf('-i'));
- });
-
- it('funde los últimos cuatro segundos, no otros', () => {
- expect(args).toContain('afade=t=out:st=36:d=4');
+describe('escucha pública', () => {
+ it('conserva la jerarquía y normaliza el formato', () => {
+ expect(claveDeEscucha('disco/01-tema.wav')).toBe('disco/01-tema.mp3');
});
- it('no funde antes de empezar en un fragmento corto', () => {
- // Un tema de tres segundos no da para un fundido de cuatro: el inicio del
- // fundido no puede ser negativo.
- const cortos = argumentosDeMuestra('a.mp3', 'b.mp3', 0, 3);
- expect(cortos).toContain('afade=t=out:st=0:d=4');
- });
-
- it('recorta lo que se le pide', () => {
- expect(args[args.indexOf('-ss') + 1]).toBe('30');
- expect(args[args.indexOf('-t') + 1]).toBe('40');
+ it('codifica la canción completa a menor calidad', () => {
+ const args = argumentosDeEscucha(
+ 'media/audio/singles/dorina.wav',
+ 'static/escucha/singles/dorina.mp3'
+ );
+ expect(args).not.toContain('-ss');
+ expect(args).not.toContain('-t');
+ expect(args).toContain('libmp3lame');
+ expect(args).toContain('96k');
+ expect(args.at(-1)).toBe('static/escucha/singles/dorina.mp3');
});
});
diff --git a/src/content/legal/condiciones-de-uso.md b/src/content/legal/condiciones-de-uso.md
index 3d8ddba..853ec8e 100644
--- a/src/content/legal/condiciones-de-uso.md
+++ b/src/content/legal/condiciones-de-uso.md
@@ -1,7 +1,7 @@
---
titulo: 'Condiciones de uso'
resumen: 'Qué puedes hacer en esta web y qué no.'
-actualizada: 2026-09-07
+actualizada: 2026-09-10
orden: 2
---
@@ -29,12 +29,13 @@ tiempo que obliga la ley, según se explica en la
## Lo que suena y lo que se compra
-En la web **suena un fragmento** de cada tema, no la canción entera. Es una
-muestra para que decidas.
+En la web se puede escuchar **la canción completa en una copia de calidad
+reducida**. Esa copia es solo para escucharla desde el sitio: que sea accesible
+no concede permiso para descargarla, redistribuirla ni reutilizarla.
-Al comprar recibes el archivo completo en MP3, con todas sus versiones
-alternativas, y queda vinculado a tu cuenta: puedes volver a descargarlo desde
-ella siempre que quieras.
+Al comprar recibes el archivo de mayor calidad disponible, con todas sus
+versiones alternativas, y queda vinculado a tu cuenta: puedes volver a
+descargarlo desde ella siempre que quieras.
## Lo que no se puede hacer
@@ -49,8 +50,8 @@ la ficha de cada tema para poder pedirla.
Con la web:
-- Intentar acceder a partes que no te corresponden, o a los archivos completos
- sin haberlos comprado.
+- Intentar acceder a partes que no te corresponden, o a los archivos originales
+ o de descarga sin haberlos comprado.
- Automatizar peticiones de forma que degraden el servicio.
- Usar el formulario de acceso o el de contacto para molestar a terceros.
diff --git a/src/lib/audio.ts b/src/lib/audio.ts
index f723137..410897a 100644
--- a/src/lib/audio.ts
+++ b/src/lib/audio.ts
@@ -1,33 +1,33 @@
/**
* Rutas de audio.
*
- * El catalogo se vende, asi que el archivo completo no vive en `static/`: se
- * guarda en un directorio privado y solo lo entrega el servidor a quien lo ha
- * comprado. Lo unico publico es un fragmento de muestra.
+ * La escucha pública contiene la canción completa con una codificación de
+ * menor calidad. El máster y la descarga siguen en un almacén privado.
*
* En el contenido, cada tema declara una *clave* relativa
* (`como-si-nada/01-como-si-nada.mp3`). De esa clave salen las dos rutas:
*
- * muestra publica static/muestras/ -> /muestras/
+ * escucha publica static/escucha/ -> /escucha/
* archivo completo / -> /descargas/
*/
import { resolve } from '$app/paths';
import type { ResolvedPathname } from '$app/types';
-/** Prefijo publico de los fragmentos de muestra. */
-export const RUTA_MUESTRAS = '/muestras';
+/** Prefijo público de las copias completas de escucha. */
+export const RUTA_ESCUCHA = '/escucha';
/**
- * URL publica del fragmento de muestra de una clave de audio.
+ * URL pública de escucha de una clave de audio.
*
* No pasa por `asset()` porque las claves salen del contenido y son dinamicas,
* mientras que `asset()` exige un archivo conocido en tiempo de compilacion. Si
* algun dia el sitio se sirviera bajo un subdirectorio, esta funcion es el
* unico sitio donde habria que anteponer la base.
*/
-export function urlMuestra(clave: string): string {
- return `${RUTA_MUESTRAS}/${clave}`;
+export function urlEscucha(clave: string): string {
+ if (clave.startsWith('/')) return clave;
+ return `${RUTA_ESCUCHA}/${clave}`;
}
/**
diff --git a/src/lib/components/FichaDeCancion.svelte b/src/lib/components/FichaDeCancion.svelte
index 81ca38b..6c8bbfb 100644
--- a/src/lib/components/FichaDeCancion.svelte
+++ b/src/lib/components/FichaDeCancion.svelte
@@ -125,7 +125,19 @@
{listaDeNombres(cancion.musica)}
{#if cancion.interpretes.length > 0}
Interpretación
- {listaDeNombres(cancion.interpretes)}
+
+ {#each cancion.interpretes as interprete, i (interprete.id + interprete.rol)}
+ {#if i > 0},
+ {/if}
+ {#if interprete.slug}
+ {interprete.nombre}
+ {:else}
+ {interprete.nombre}
+ {/if}
+ {/each}
+
{/if}
diff --git a/src/lib/components/TablaCanciones.svelte b/src/lib/components/TablaCanciones.svelte
index da4f3bb..cdf36a9 100644
--- a/src/lib/components/TablaCanciones.svelte
+++ b/src/lib/components/TablaCanciones.svelte
@@ -348,7 +348,8 @@
+{c.etiquetas.length - CUANTAS_ETIQUETAS}
{/if}
{#if c.generos.length === 0 && c.etiquetas.length === 0}
- {listaDeNombres(c.interpretes)}
+ {listaDeNombres(c.interpretes.map((i) => i.nombre))}
{/if}
diff --git a/src/lib/components/TarjetaCancion.svelte.spec.ts b/src/lib/components/TarjetaCancion.svelte.spec.ts
index 9e1a986..e73c5b4 100644
--- a/src/lib/components/TarjetaCancion.svelte.spec.ts
+++ b/src/lib/components/TarjetaCancion.svelte.spec.ts
@@ -1,4 +1,4 @@
-import { page } from '@vitest/browser/context';
+import { page } from 'vitest/browser';
import { describe, expect, it, vi } from 'vitest';
import { render } from 'vitest-browser-svelte';
import TarjetaCancion from './TarjetaCancion.svelte';
@@ -54,6 +54,7 @@ vi.mock('$app/state', () => ({
function cancion(parcial: Partial = {}): Cancion {
return {
+ codigo: 'CAN-000001',
slug: 'como-si-nada',
titulo: 'Como si nada',
estilo: 'baladas-romanticas',
@@ -64,7 +65,16 @@ function cancion(parcial: Partial = {}): Cancion {
ano: 2024,
letra: ['Senza Paura'],
musica: ['Senza Paura'],
- interpretes: ['Marta Cifuentes'],
+ interpretes: [
+ {
+ id: 'marta-cifuentes',
+ codigo: 'ART-000001',
+ slug: 'marta-cifuentes',
+ nombre: 'Marta Cifuentes',
+ tipo: 'persona',
+ rol: 'principal'
+ }
+ ],
destacada: true,
etiquetas: ['Desamor', 'Dueto'],
generos: [],
@@ -86,7 +96,7 @@ function pista(id = 'como-si-nada'): PistaReproductor {
id,
cancionSlug: id,
titulo: 'Como si nada',
- audio: '/muestras/como-si-nada/01-como-si-nada.mp3',
+ audio: '/escucha/como-si-nada/01-como-si-nada.mp3',
albumTitulo: 'Como si nada',
albumSlug: 'como-si-nada',
portada: '/images/albumes/como-si-nada.svg',
diff --git a/src/lib/components/player/BarraReproductor.svelte b/src/lib/components/player/BarraReproductor.svelte
index 551e118..e92c500 100644
--- a/src/lib/components/player/BarraReproductor.svelte
+++ b/src/lib/components/player/BarraReproductor.svelte
@@ -114,12 +114,7 @@
{pista.titulo}
-
- Muestra
+ Calidad de escucha
{pista.albumTitulo}
@@ -259,7 +254,7 @@
min-width: 0;
}
- .muestra {
+ .calidad {
flex: none;
padding: 0 0.4em;
border: 1px solid var(--c-border);
@@ -350,7 +345,7 @@
/*
* El mismo metal que los botones del sitio: la clase `.oro` de `app.css`
* pone el degradado, el filo de luz y el barrido al pasar por encima. Antes
- * era `--c-accent` plano y, al lado de un «Escuchar la muestra» dorado,
+ * era `--c-accent` plano y, al lado de un botón de escucha dorado,
* parecía otro color.
*/
.control.principal {
diff --git a/src/lib/content/schema.ts b/src/lib/content/schema.ts
index 594ac1c..6a8dae3 100644
--- a/src/lib/content/schema.ts
+++ b/src/lib/content/schema.ts
@@ -208,10 +208,13 @@ function parsearVersion(datos: Datos, indice: number, archivo: string): VersionM
// Sin `id` explicito se deriva del nombre: basta para distinguirlas
// dentro del tema, que es el unico ambito en el que viven.
id: textoOpcional(datos, 'id', `${archivo} (${campo})`) ?? aSlug(nombre),
+ codigo: `LEG-V-${indice + 1}`,
+ slug: aSlug(nombre),
nombre,
audio,
duracion: duracion(datos, 'duracion', `${archivo} (${campo})`),
- nota: textoOpcional(datos, 'nota', `${archivo} (${campo})`)
+ nota: textoOpcional(datos, 'nota', `${archivo} (${campo})`),
+ interpretes: []
};
}
@@ -237,6 +240,7 @@ export function parsearCancion(datos: Datos, slug: string, archivo: string): Can
}
return {
+ codigo: `LEG-${slug.toUpperCase()}`,
slug,
titulo: texto(datos, 'titulo', archivo),
estilo: texto(datos, 'estilo', archivo),
@@ -250,7 +254,13 @@ export function parsearCancion(datos: Datos, slug: string, archivo: string): Can
// La autoria por defecto es del artista: es su propia web.
letra: listaDeTextos(datos, 'letra', archivo, autoria),
musica: listaDeTextos(datos, 'musica', archivo, autoria),
- interpretes: listaDeTextos(datos, 'interpretes', archivo),
+ interpretes: listaDeTextos(datos, 'interpretes', archivo).map((nombre, indice) => ({
+ id: `legacy-${aSlug(nombre)}`,
+ codigo: `LEG-ART-${indice + 1}`,
+ nombre,
+ tipo: 'persona',
+ rol: 'principal'
+ })),
destacada: booleano(datos, 'destacada', archivo),
etiquetas: listaDeTextos(datos, 'etiquetas', archivo),
// Los generos viven en la base, no en el frontmatter: este lector es del
diff --git a/src/lib/navegacion.ts b/src/lib/navegacion.ts
index 3e16ec6..a251340 100644
--- a/src/lib/navegacion.ts
+++ b/src/lib/navegacion.ts
@@ -14,6 +14,7 @@ import type { ResolvedPathname } from '$app/types';
*/
export const navegacion: { href: ResolvedPathname; texto: string }[] = [
{ href: resolve('/musica'), texto: 'Música' },
+ { href: resolve('/interpretes'), texto: 'Intérpretes' },
{ href: resolve('/taller'), texto: 'Taller de letras' },
{ href: resolve('/generos'), texto: 'Géneros' },
{ href: resolve('/blog'), texto: 'Blog' },
diff --git a/src/lib/player/pista.ts b/src/lib/player/pista.ts
index be22749..6822cb6 100644
--- a/src/lib/player/pista.ts
+++ b/src/lib/player/pista.ts
@@ -5,11 +5,10 @@
* desnormalizadas, con su portada y sus etiquetas resueltas. Esta es la unica
* conversion entre los dos mundos.
*
- * Lo que suena en la web es siempre el fragmento de muestra, nunca el archivo
- * completo: ese solo se entrega por descarga a quien lo ha comprado.
+ * Lo que suena en la web es la canción completa en calidad de escucha. El
+ * archivo de compra permanece privado y se entrega por una ruta autorizada.
*/
-import { urlMuestra } from '$lib/audio';
/*
* Del catálogo que baja por `page.data`, no de los archivos. `aPistas` se
* llama siempre dentro de un `$derived` de un componente, así que la lectura
@@ -43,7 +42,7 @@ export function aPista(cancion: Cancion): PistaReproductor {
id: cancion.slug,
cancionSlug: cancion.slug,
titulo: cancion.titulo,
- audio: cancion.audio ? urlMuestra(cancion.audio) : '',
+ audio: cancion.audio ?? '',
duracion: cancion.duracion,
...contexto(cancion)
};
@@ -60,7 +59,7 @@ export function aPistaDeVersion(cancion: Cancion, version: VersionMusical): Pist
id: `${cancion.slug}#${version.id}`,
cancionSlug: cancion.slug,
titulo: `${cancion.titulo} · ${version.nombre}`,
- audio: urlMuestra(version.audio),
+ audio: version.audio ?? '',
duracion: version.duracion,
...contexto(cancion)
};
diff --git a/src/lib/player/player.svelte.ts b/src/lib/player/player.svelte.ts
index 6a82bc2..f867141 100644
--- a/src/lib/player/player.svelte.ts
+++ b/src/lib/player/player.svelte.ts
@@ -31,7 +31,7 @@ export interface PistaReproductor {
/** Slug del tema al que pertenece, para enlazar a su ficha. */
cancionSlug: string;
titulo: string;
- /** URL publica del fragmento de muestra. */
+ /** URL pública de la canción completa en calidad de escucha. */
audio: string;
albumTitulo: string;
albumSlug: string;
diff --git a/src/lib/server/artistas.ts b/src/lib/server/artistas.ts
new file mode 100644
index 0000000..90689bc
--- /dev/null
+++ b/src/lib/server/artistas.ts
@@ -0,0 +1,138 @@
+import { and, asc, eq } from 'drizzle-orm';
+import { alias } from 'drizzle-orm/pg-core';
+import { db } from './db';
+import { artista, artistaIdentificador, medio, pais } from './db/schema';
+import { leerCatalogo } from './catalogo';
+import { componer } from './markdown';
+import type { Cancion, TipoArtista } from '$lib/types';
+
+export interface ResumenDeArtista {
+ id: string;
+ codigo: string;
+ slug: string;
+ nombre: string;
+ tipo: TipoArtista;
+ descripcion: string;
+ imagen?: string;
+ pais?: string;
+ lugarOrigen?: string;
+ inicio?: number;
+ fin?: number;
+ totalCanciones: number;
+}
+
+export interface FichaDeArtista extends ResumenDeArtista {
+ biografia: string;
+ sitioWeb?: string;
+ identificadores: { sistema: string; valor: string }[];
+ canciones: Cancion[];
+}
+
+function rutaPublica(clave: string | null): string | undefined {
+ return clave ? `/${clave}` : undefined;
+}
+
+function participa(cancion: Cancion, artistaId: string): boolean {
+ return (
+ cancion.interpretes.some((i) => i.id === artistaId) ||
+ cancion.versiones.some((v) => v.interpretes.some((i) => i.id === artistaId))
+ );
+}
+
+/** Directorio público de identidades artísticas, nunca personas en borrador. */
+export async function artistasPublicos(): Promise {
+ const imagen = alias(medio, 'imagen_artista_publica');
+ const [filas, catalogo] = await Promise.all([
+ db
+ .select({
+ id: artista.id,
+ codigo: artista.codigo,
+ slug: artista.slug,
+ nombre: artista.nombre,
+ tipo: artista.tipo,
+ descripcion: artista.descripcionCorta,
+ imagenClave: imagen.clave,
+ pais: pais.nombre,
+ lugarOrigen: artista.lugarOrigen,
+ inicio: artista.inicio,
+ fin: artista.fin
+ })
+ .from(artista)
+ .leftJoin(imagen, eq(imagen.id, artista.imagenId))
+ .leftJoin(pais, eq(pais.codigo, artista.paisCodigo))
+ .where(eq(artista.estado, 'publicado'))
+ .orderBy(asc(artista.nombre)),
+ leerCatalogo()
+ ]);
+
+ return filas.map((fila) => ({
+ id: fila.id,
+ codigo: fila.codigo,
+ slug: fila.slug,
+ nombre: fila.nombre,
+ tipo: fila.tipo,
+ descripcion: fila.descripcion,
+ imagen: rutaPublica(fila.imagenClave),
+ pais: fila.pais ?? undefined,
+ lugarOrigen: fila.lugarOrigen ?? undefined,
+ inicio: fila.inicio ?? undefined,
+ fin: fila.fin ?? undefined,
+ totalCanciones: catalogo.canciones.filter((c) => participa(c, fila.id)).length
+ }));
+}
+
+/** Ficha pública y discografía de una identidad artística. */
+export async function obtenerArtistaPublico(slug: string): Promise {
+ const imagen = alias(medio, 'imagen_artista_ficha');
+ const [fila] = await db
+ .select({
+ id: artista.id,
+ codigo: artista.codigo,
+ slug: artista.slug,
+ nombre: artista.nombre,
+ tipo: artista.tipo,
+ descripcion: artista.descripcionCorta,
+ biografia: artista.biografia,
+ imagenClave: imagen.clave,
+ pais: pais.nombre,
+ lugarOrigen: artista.lugarOrigen,
+ inicio: artista.inicio,
+ fin: artista.fin,
+ sitioWeb: artista.sitioWeb
+ })
+ .from(artista)
+ .leftJoin(imagen, eq(imagen.id, artista.imagenId))
+ .leftJoin(pais, eq(pais.codigo, artista.paisCodigo))
+ .where(and(eq(artista.slug, slug), eq(artista.estado, 'publicado')))
+ .limit(1);
+
+ if (!fila) return undefined;
+ const [catalogo, identificadores] = await Promise.all([
+ leerCatalogo(),
+ db
+ .select({ sistema: artistaIdentificador.sistema, valor: artistaIdentificador.valor })
+ .from(artistaIdentificador)
+ .where(eq(artistaIdentificador.artistaId, fila.id))
+ .orderBy(asc(artistaIdentificador.sistema))
+ ]);
+ const canciones = catalogo.canciones.filter((c) => participa(c, fila.id));
+
+ return {
+ id: fila.id,
+ codigo: fila.codigo,
+ slug: fila.slug,
+ nombre: fila.nombre,
+ tipo: fila.tipo,
+ descripcion: fila.descripcion,
+ biografia: componer(fila.biografia),
+ imagen: rutaPublica(fila.imagenClave),
+ pais: fila.pais ?? undefined,
+ lugarOrigen: fila.lugarOrigen ?? undefined,
+ inicio: fila.inicio ?? undefined,
+ fin: fila.fin ?? undefined,
+ sitioWeb: fila.sitioWeb ?? undefined,
+ identificadores,
+ canciones,
+ totalCanciones: canciones.length
+ };
+}
diff --git a/src/lib/server/audios.ts b/src/lib/server/audios.ts
new file mode 100644
index 0000000..1e064a0
--- /dev/null
+++ b/src/lib/server/audios.ts
@@ -0,0 +1,76 @@
+/** Selección servidor-a-servidor del archivo privado que incluye una compra. */
+
+import { and, asc, eq, inArray, isNull, ne, sql } from 'drizzle-orm';
+import { db } from './db';
+import { cancion, cancionAudio, medio } from './db/schema';
+
+export interface ArchivoComprado {
+ cancionId: string;
+ cancionSlug: string;
+ principalSlug: string;
+ titulo: string;
+ versionNombre?: string;
+ clave: string;
+}
+
+/**
+ * Resuelve primero la entidad musical y después una representación privada.
+ * La descarga explícita gana al máster; ninguno de los dos cruza el contrato
+ * público del catálogo.
+ */
+export async function archivoComprado(
+ principalSlug: string,
+ versionCodigo?: string
+): Promise {
+ const [principal] = await db
+ .select({ id: cancion.id, slug: cancion.slug, titulo: cancion.titulo })
+ .from(cancion)
+ .where(and(eq(cancion.slug, principalSlug), isNull(cancion.versionDeId)))
+ .limit(1);
+ if (!principal) return undefined;
+
+ const destino = versionCodigo
+ ? (
+ await db
+ .select({
+ id: cancion.id,
+ slug: cancion.slug,
+ titulo: cancion.titulo,
+ versionNombre: cancion.versionNombre
+ })
+ .from(cancion)
+ .where(
+ and(
+ eq(cancion.versionDeId, principal.id),
+ eq(cancion.versionCodigo, versionCodigo),
+ ne(cancion.estado, 'borrador')
+ )
+ )
+ .limit(1)
+ )[0]
+ : { ...principal, versionNombre: null };
+ if (!destino) return undefined;
+
+ const [audio] = await db
+ .select({ clave: medio.clave })
+ .from(cancionAudio)
+ .innerJoin(medio, eq(medio.id, cancionAudio.medioId))
+ .where(
+ and(eq(cancionAudio.cancionId, destino.id), inArray(cancionAudio.uso, ['descarga', 'master']))
+ )
+ .orderBy(
+ sql`case when ${cancionAudio.uso} = 'descarga' then 0 else 1 end`,
+ asc(cancionAudio.orden)
+ )
+ .limit(1);
+ if (!audio) return undefined;
+
+ return {
+ cancionId: destino.id,
+ cancionSlug: destino.slug,
+ principalSlug: principal.slug,
+ titulo: principal.titulo,
+ versionNombre: destino.versionNombre ?? undefined,
+ clave: audio.clave.replace(/^audio\//, '')
+ };
+}
diff --git a/src/lib/server/catalogo.ts b/src/lib/server/catalogo.ts
index 294fea6..8a20887 100644
--- a/src/lib/server/catalogo.ts
+++ b/src/lib/server/catalogo.ts
@@ -30,11 +30,14 @@ import { db } from './db';
import {
album,
albumEnlace,
+ artista,
autoria,
cancion,
+ cancionAudio,
cancionEnlace,
cancionEtiqueta,
cancionGenero,
+ cancionInterprete,
cancionPersona,
creditoAlbum,
estilo,
@@ -118,15 +121,17 @@ async function cargar(): Promise {
* `medio` por su audio y otra vez por su portada, y sin alias Postgres ve
* un solo `medio` y devuelve la misma fila para los dos.
*/
- const audio = alias(medio, 'audio');
const portadaCancion = alias(medio, 'portada_cancion');
const portadaAlbum = alias(medio, 'portada_album');
+ const imagenArtista = alias(medio, 'imagen_artista');
const [
filasEstilo,
filasAlbum,
filasCancion,
personas,
+ interpretes,
+ audiosDeEscucha,
etiquetas,
enlacesCancion,
enlacesAlbum,
@@ -163,14 +168,11 @@ async function cargar(): Promise {
fila: cancion,
estiloSlug: estilo.slug,
albumSlug: album.slug,
- audioClave: audio.clave,
- audioDuracion: audio.duracionS,
portadaClave: portadaCancion.clave
})
.from(cancion)
.innerJoin(estilo, eq(estilo.id, cancion.estiloId))
.leftJoin(album, eq(album.id, cancion.albumId))
- .leftJoin(audio, eq(audio.id, cancion.audioId))
.leftJoin(portadaCancion, eq(portadaCancion.id, cancion.portadaId))
.where(
and(
@@ -192,6 +194,36 @@ async function cargar(): Promise {
.innerJoin(persona, eq(persona.id, cancionPersona.personaId))
.orderBy(asc(cancionPersona.orden)),
+ db
+ .select({
+ cancionId: cancionInterprete.cancionId,
+ id: artista.id,
+ codigo: artista.codigo,
+ slug: artista.slug,
+ nombre: artista.nombre,
+ tipo: artista.tipo,
+ estado: artista.estado,
+ rol: cancionInterprete.rol,
+ instrumento: cancionInterprete.instrumento,
+ acreditadoComo: cancionInterprete.acreditadoComo,
+ imagenClave: imagenArtista.clave
+ })
+ .from(cancionInterprete)
+ .innerJoin(artista, eq(artista.id, cancionInterprete.artistaId))
+ .leftJoin(imagenArtista, eq(imagenArtista.id, artista.imagenId))
+ .orderBy(asc(cancionInterprete.orden), asc(artista.nombre)),
+
+ db
+ .select({
+ cancionId: cancionAudio.cancionId,
+ clave: medio.clave,
+ duracion: medio.duracionS
+ })
+ .from(cancionAudio)
+ .innerJoin(medio, eq(medio.id, cancionAudio.medioId))
+ .where(and(eq(cancionAudio.uso, 'stream'), eq(medio.publico, true)))
+ .orderBy(asc(cancionAudio.orden)),
+
db
.select({ cancionId: cancionEtiqueta.cancionId, nombre: etiqueta.nombre })
.from(cancionEtiqueta)
@@ -265,12 +297,14 @@ async function cargar(): Promise {
const porCancion = {
personas: porClave(personas, (p) => p.cancionId),
+ interpretes: porClave(interpretes, (i) => i.cancionId),
etiquetas: porClave(etiquetas, (e) => e.cancionId),
generos: porClave(generosDeCancion, (g) => g.cancionId),
enlaces: porClave(enlacesCancion, (e) => e.cancionId),
videos: porClave(videos, (v) => v.cancionId),
partes: porClave(partes, (p) => p.cancionId)
};
+ const audioDeEscucha = new Map(audiosDeEscucha.map((a) => [a.cancionId, a]));
const traduccionDe = new Map(traducciones.map((t) => [t.cancionId, t.texto]));
const registroDe = new Map(registros.map((r) => [r.cancionId, r]));
const enlacesDeAlbum = porClave(enlacesAlbum, (e) => e.albumId);
@@ -331,20 +365,39 @@ async function cargar(): Promise {
const canciones: Cancion[] = filasCancion
.filter((f) => f.fila.versionDeId === null)
- .map(({ fila, estiloSlug, albumSlug, audioClave, audioDuracion, portadaClave }) => {
+ .map(({ fila, estiloSlug, albumSlug, portadaClave }) => {
const suyas = porCancion.personas.get(fila.id) ?? [];
+ const susInterpretes = porCancion.interpretes.get(fila.id) ?? [];
+ const escucha = audioDeEscucha.get(fila.id);
const registro = registroDe.get(fila.id);
const misPartes = porCancion.partes.get(fila.id) ?? [];
const versiones: VersionMusical[] = (versionesDe.get(fila.id) ?? [])
.sort((a, b) => a.fila.versionOrden - b.fila.versionOrden)
- .map((v) => ({
- id: v.fila.slug.replace(`${fila.slug}-`, ''),
- nombre: v.fila.versionNombre ?? '',
- audio: v.audioClave?.replace(/^audio\//, '') ?? '',
- duracion: v.fila.duracionS ?? v.audioDuracion ?? undefined,
- nota: v.fila.versionNota ?? undefined
- }));
+ .map((v) => {
+ const escuchaVersion = audioDeEscucha.get(v.fila.id);
+ const interpretesVersion = porCancion.interpretes.get(v.fila.id) ?? [];
+ return {
+ id: v.fila.versionCodigo ?? v.fila.slug.replace(`${fila.slug}-`, ''),
+ codigo: v.fila.codigo,
+ slug: v.fila.slug,
+ nombre: v.fila.versionNombre ?? '',
+ audio: rutaPublica(escuchaVersion?.clave ?? null),
+ duracion: v.fila.duracionS ?? escuchaVersion?.duracion ?? undefined,
+ nota: v.fila.versionNota ?? undefined,
+ interpretes: interpretesVersion.map((i) => ({
+ id: i.id,
+ codigo: i.codigo,
+ slug: i.estado === 'publicado' ? i.slug : undefined,
+ nombre: i.acreditadoComo ?? i.nombre,
+ tipo: i.tipo,
+ rol: i.rol,
+ instrumento: i.instrumento ?? undefined,
+ acreditadoComo: i.acreditadoComo ?? undefined,
+ imagen: i.estado === 'publicado' ? rutaPublica(i.imagenClave) : undefined
+ }))
+ };
+ });
const registroDeObra: RegistroDeObra = {
iswc: registro?.iswc ?? undefined,
@@ -365,17 +418,28 @@ async function cargar(): Promise {
}));
return {
+ codigo: fila.codigo,
slug: fila.slug,
titulo: fila.titulo,
estilo: estiloSlug,
album: albumSlug ?? null,
numero: fila.numero,
- audio: audioClave?.replace(/^audio\//, ''),
- duracion: fila.duracionS ?? audioDuracion ?? undefined,
+ audio: rutaPublica(escucha?.clave ?? null),
+ duracion: fila.duracionS ?? escucha?.duracion ?? undefined,
ano: fila.ano ?? undefined,
letra: suyas.filter((p) => p.rol === 'letra').map((p) => p.nombre),
musica: suyas.filter((p) => p.rol === 'musica').map((p) => p.nombre),
- interpretes: suyas.filter((p) => p.rol === 'interprete').map((p) => p.nombre),
+ interpretes: susInterpretes.map((i) => ({
+ id: i.id,
+ codigo: i.codigo,
+ slug: i.estado === 'publicado' ? i.slug : undefined,
+ nombre: i.acreditadoComo ?? i.nombre,
+ tipo: i.tipo,
+ rol: i.rol,
+ instrumento: i.instrumento ?? undefined,
+ acreditadoComo: i.acreditadoComo ?? undefined,
+ imagen: i.estado === 'publicado' ? rutaPublica(i.imagenClave) : undefined
+ })),
destacada: fila.destacada,
etiquetas: (porCancion.etiquetas.get(fila.id) ?? []).map((e) => e.nombre),
generos: (porCancion.generos.get(fila.id) ?? []).map((g) => ({
diff --git a/src/lib/server/db/schema/artistas.ts b/src/lib/server/db/schema/artistas.ts
index ffa745e..8e73ba7 100644
--- a/src/lib/server/db/schema/artistas.ts
+++ b/src/lib/server/db/schema/artistas.ts
@@ -6,6 +6,7 @@ import {
check,
index,
integer,
+ pgSequence,
pgTable,
primaryKey,
text,
@@ -16,6 +17,7 @@ import { ahora, estado, id, instante, procedencia } from './comun';
export const TIPOS_ARTISTA = ['persona', 'grupo', 'proyecto'] as const;
export const RELACIONES_ARTISTA_PERSONA = ['identidad', 'miembro', 'fundador'] as const;
+export const artistaCodigoSeq = pgSequence('artista_codigo_seq');
/**
* Una identidad acreditada ante el público. No equivale necesariamente a una
diff --git a/src/lib/server/db/schema/base.ts b/src/lib/server/db/schema/base.ts
index 6fcb8b6..cee4a8a 100644
--- a/src/lib/server/db/schema/base.ts
+++ b/src/lib/server/db/schema/base.ts
@@ -48,10 +48,9 @@ export const medio = pgTable(
/**
* Si se puede pedir por URL sin más.
*
- * Los fragmentos de muestra sí; el audio completo no, nunca. Hasta ahora
- * eso lo garantizaba la carpeta en la que estaba el archivo —un directorio
- * privado fuera de `build/`—, que es una garantía que depende de que nadie
- * mueva nada. Aquí es un dato, y el que sirve los archivos lo comprueba.
+ * Las copias completas de escucha sí; los másteres y descargas no. Antes
+ * eso dependía solo de la carpeta física. Aquí es un dato y cada consumidor
+ * selecciona además el uso concreto en `cancion_audio`.
*
* Con los medios en su propio dominio esto se vuelve más importante, no
* menos: allí la cookie de sesión no viaja, así que lo privado se entrega
diff --git a/src/lib/server/db/schema/catalogo.ts b/src/lib/server/db/schema/catalogo.ts
index 667960c..ec6e89d 100644
--- a/src/lib/server/db/schema/catalogo.ts
+++ b/src/lib/server/db/schema/catalogo.ts
@@ -16,6 +16,7 @@ import {
index,
integer,
numeric,
+ pgSequence,
pgTable,
primaryKey,
text,
@@ -25,6 +26,8 @@ import { ahora, estado, id, instante } from './comun';
import { medio, pais, persona } from './base';
import { artista } from './artistas';
+export const cancionCodigoSeq = pgSequence('cancion_codigo_seq');
+
/**
* Una sección del catálogo: baladas románticas, clásica, rock, pop melódico.
*
diff --git a/src/lib/server/descargas.ts b/src/lib/server/descargas.ts
index 5618f99..7cc801e 100644
--- a/src/lib/server/descargas.ts
+++ b/src/lib/server/descargas.ts
@@ -1,12 +1,11 @@
/** Registro auditable del inicio de una descarga autorizada. */
-import { eq } from 'drizzle-orm';
import { db } from './db';
-import { cancion, descarga } from './db/schema';
+import { descarga } from './db/schema';
export interface EntregaIniciada {
usuarioId: string;
- cancionSlug: string;
+ cancionId: string;
ip: string | null;
agente: string | null;
}
@@ -16,17 +15,9 @@ export interface EntregaIniciada {
* navegador haya terminado de guardarlo: HTTP no proporciona ese acuse.
*/
export async function registrarEntregaIniciada(datos: EntregaIniciada): Promise {
- const [tema] = await db
- .select({ id: cancion.id })
- .from(cancion)
- .where(eq(cancion.slug, datos.cancionSlug))
- .limit(1);
-
- if (!tema) throw new Error(`No existe la canción descargada «${datos.cancionSlug}».`);
-
await db.insert(descarga).values({
usuarioId: datos.usuarioId,
- cancionId: tema.id,
+ cancionId: datos.cancionId,
ip: datos.ip,
agente: datos.agente
});
diff --git a/src/lib/server/markdown.spec.ts b/src/lib/server/markdown.spec.ts
new file mode 100644
index 0000000..e40aac6
--- /dev/null
+++ b/src/lib/server/markdown.spec.ts
@@ -0,0 +1,16 @@
+import { describe, expect, it } from 'vitest';
+import { componer } from './markdown';
+
+describe('componer', () => {
+ it('conserva Markdown editorial', () => {
+ expect(componer('## Historia\n\nUna **voz**.')).toContain('voz ');
+ expect(componer('## Historia')).toContain('id="historia"');
+ });
+
+ it('no deja ejecutar HTML ni protocolos activos', () => {
+ const html = componer('\n\n[abre](javascript:alert(1))');
+ expect(html).not.toContain('
+
+Artistas · Panel
+
+
+
+
+{#if form?.error}{form.error}
{/if}
+
+Buscar
+
+ Identidad Tipo Estado Grabaciones
+ {#each encontrados as artista (artista.id)}
+ {artista.nombre} {artista.codigo} · {artista.slug} {artista.tipo} {artista.estado} {artista.grabaciones}
+ {/each}
+
+
+
+
diff --git a/src/panel/rutas/(dentro)/artistas/[slug]/+page.server.ts b/src/panel/rutas/(dentro)/artistas/[slug]/+page.server.ts
new file mode 100644
index 0000000..7751ea1
--- /dev/null
+++ b/src/panel/rutas/(dentro)/artistas/[slug]/+page.server.ts
@@ -0,0 +1,58 @@
+import { error, fail } from '@sveltejs/kit';
+import {
+ artistaParaEditar,
+ guardarArtista,
+ opcionesDeArtista,
+ revisarArtista,
+ type CambiosDeArtista,
+ type Estado
+} from '$lib/server/panel-artistas';
+import type { TipoArtista } from '$lib/types';
+import type { Actions, PageServerLoad } from './$types';
+
+export const load: PageServerLoad = async ({ params }) => {
+ const [artista, opciones] = await Promise.all([
+ artistaParaEditar(params.slug),
+ opcionesDeArtista()
+ ]);
+ if (!artista) error(404, 'No existe esa identidad artística.');
+ return { artista, ...opciones };
+};
+
+const numero = (valor: FormDataEntryValue | null) =>
+ String(valor ?? '').trim() ? Number(valor) : null;
+
+export const actions: Actions = {
+ guardar: async ({ request, params }) => {
+ const datos = await request.formData();
+ const identificadores = String(datos.get('identificadores') ?? '')
+ .split('\n')
+ .map((l) => l.trim())
+ .filter(Boolean)
+ .map((linea) => {
+ const corte = linea.indexOf(':');
+ return {
+ sistema: corte < 0 ? '' : linea.slice(0, corte).trim(),
+ valor: corte < 0 ? linea : linea.slice(corte + 1).trim()
+ };
+ });
+ const cambios: CambiosDeArtista = {
+ nombre: String(datos.get('nombre') ?? ''),
+ tipo: String(datos.get('tipo') ?? 'persona') as TipoArtista,
+ descripcion: String(datos.get('descripcion') ?? ''),
+ biografia: String(datos.get('biografia') ?? ''),
+ imagenId: String(datos.get('imagenId') ?? '') || null,
+ paisCodigo: String(datos.get('paisCodigo') ?? '') || null,
+ lugarOrigen: String(datos.get('lugarOrigen') ?? ''),
+ inicio: numero(datos.get('inicio')),
+ fin: numero(datos.get('fin')),
+ sitioWeb: String(datos.get('sitioWeb') ?? ''),
+ estado: String(datos.get('estado') ?? 'borrador') as Estado,
+ identificadores
+ };
+ const errores = revisarArtista(cambios);
+ if (Object.keys(errores).length) return fail(400, { errores });
+ if (!(await guardarArtista(params.slug, cambios))) error(404, 'La ficha ya no existe.');
+ return { guardado: true };
+ }
+};
diff --git a/src/panel/rutas/(dentro)/artistas/[slug]/+page.svelte b/src/panel/rutas/(dentro)/artistas/[slug]/+page.svelte
new file mode 100644
index 0000000..abc259a
--- /dev/null
+++ b/src/panel/rutas/(dentro)/artistas/[slug]/+page.svelte
@@ -0,0 +1,146 @@
+
+
+{data.artista.nombre} · Panel
+← Artistas
+
+
+
diff --git a/src/panel/rutas/(dentro)/canciones/[slug]/+page.server.ts b/src/panel/rutas/(dentro)/canciones/[slug]/+page.server.ts
index c568fda..0ac2a03 100644
--- a/src/panel/rutas/(dentro)/canciones/[slug]/+page.server.ts
+++ b/src/panel/rutas/(dentro)/canciones/[slug]/+page.server.ts
@@ -24,6 +24,17 @@ function numeroDe(valor: FormDataEntryValue | null): number | null {
export const actions: Actions = {
default: async ({ request, params }) => {
const datos = await request.formData();
+ const versiones = datos.getAll('versionId').map((valor) => {
+ const id = String(valor);
+ return {
+ id,
+ nombre: String(datos.get(`versionNombre:${id}`) ?? ''),
+ nota: String(datos.get(`versionNota:${id}`) ?? ''),
+ estado: String(datos.get(`versionEstado:${id}`) ?? 'borrador') as Estado
+ };
+ });
+ const nombreVersion = String(datos.get('nuevaVersionNombre') ?? '').trim();
+ const codigoVersion = String(datos.get('nuevaVersionCodigo') ?? '').trim();
const cambios: CambiosDeCancion = {
titulo: String(datos.get('titulo') ?? ''),
@@ -35,10 +46,17 @@ export const actions: Actions = {
estado: String(datos.get('estado') ?? '') as Estado,
instrumental: datos.get('instrumental') !== null,
destacada: datos.get('destacada') !== null,
- alaVenta: datos.get('alaVenta') !== null
+ alaVenta: datos.get('alaVenta') !== null,
+ interpreteIds: datos.getAll('interpreteId').map(String),
+ versiones,
+ nuevaVersion: { nombre: nombreVersion, codigo: codigoVersion }
};
const errores = revisarCancion(cambios);
+ const actual = await cancionParaEditar(params.slug);
+ if (cambios.estado === 'publicado' && !actual?.tieneAudio) {
+ errores.audio = 'No se puede publicar sin una representación completa de escucha.';
+ }
if (Object.keys(errores).length > 0) return fail(400, { errores, cambios });
const guardado = await guardarCancion(params.slug, cambios);
diff --git a/src/panel/rutas/(dentro)/canciones/[slug]/+page.svelte b/src/panel/rutas/(dentro)/canciones/[slug]/+page.svelte
index eee8435..bf02c54 100644
--- a/src/panel/rutas/(dentro)/canciones/[slug]/+page.svelte
+++ b/src/panel/rutas/(dentro)/canciones/[slug]/+page.svelte
@@ -15,7 +15,7 @@
let { data, form } = $props();
- const copiar = (c: CambiosDeCancion): CambiosDeCancion => ({
+ const copiar = (c: CambiosDeCancion | typeof data.cancion): CambiosDeCancion => ({
titulo: c.titulo,
letra: c.letra,
inspiracion: c.inspiracion,
@@ -25,16 +25,22 @@
estado: c.estado,
instrumental: c.instrumental,
destacada: c.destacada,
- alaVenta: c.alaVenta
+ alaVenta: c.alaVenta,
+ interpreteIds: [...c.interpreteIds],
+ versiones: c.versiones.map((v) => ({
+ id: v.id,
+ nombre: v.nombre,
+ nota: v.nota,
+ estado: v.estado
+ })),
+ nuevaVersion: 'nuevaVersion' in c ? { ...c.nuevaVersion } : { nombre: '', codigo: '' }
});
let campos = $state(untrack(() => copiar(form?.cambios ?? data.cancion)));
let guardado = $state(untrack(() => copiar(data.cancion)));
let guardando = $state(false);
- const sinGuardar = $derived(
- (Object.keys(guardado) as (keyof CambiosDeCancion)[]).some((k) => campos[k] !== guardado[k])
- );
+ const sinGuardar = $derived(JSON.stringify(campos) !== JSON.stringify(guardado));
const enLaWeb = $derived(`${site.url}/canciones/${data.cancion.slug}`);
const errores = $derived(form?.errores ?? {});
@@ -113,6 +119,7 @@
{/if}
{#if errores.titulo}{errores.titulo}
{/if}
+ {#if errores.audio}{errores.audio}
{/if}
@@ -175,6 +182,85 @@
+
+ Intérpretes principales
+ Son identidades públicas, no nombres copiados dentro de la canción.
+
+ {#each data.cancion.artistas as artista (artista.id)}
+
+
+ {artista.nombre} {artista.codigo}
+
+ {/each}
+
+ {#if errores.interpretes}{errores.interpretes} {/if}
+
+
+
+
De dónde sale
@@ -348,6 +434,60 @@
cursor: pointer;
}
+ .interpretes {
+ margin: 0;
+ padding: var(--sp-4);
+ border: 1px solid var(--c-border);
+ }
+ .interpretes legend {
+ padding-inline: var(--sp-2);
+ }
+ .opciones {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--sp-2) var(--sp-5);
+ margin-top: var(--sp-3);
+ }
+ .opciones label {
+ display: flex;
+ align-items: center;
+ gap: 0.45rem;
+ color: var(--c-text);
+ }
+ .opciones small {
+ color: var(--c-text-muted);
+ font-family: var(--font-mono);
+ }
+ .opciones .retirado {
+ opacity: 0.65;
+ }
+ .versiones {
+ padding-block: var(--sp-4);
+ border-block: 1px solid var(--c-border);
+ }
+ .lista-versiones {
+ display: grid;
+ gap: var(--sp-3);
+ padding: 0;
+ list-style: none;
+ }
+ .lista-versiones li {
+ display: grid;
+ grid-template-columns: 1fr 2fr minmax(8rem, 0.6fr);
+ gap: var(--sp-3);
+ padding: var(--sp-3);
+ background: var(--c-bg-raised);
+ }
+ .lista-versiones small {
+ grid-column: 1 / -1;
+ }
+ .nueva-version {
+ display: grid;
+ grid-template-columns: 2fr 1fr;
+ gap: var(--sp-3);
+ margin-top: var(--sp-4);
+ }
+
/*
* La letra se lleva la altura que queda de ventana. Es donde se pasa el
* rato, y en una caja de seis líneas se escribe mirando por una rendija.
diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts
index e16234f..d25d33f 100644
--- a/src/routes/+layout.server.ts
+++ b/src/routes/+layout.server.ts
@@ -37,16 +37,23 @@ export async function load({ locals, cookies, url }) {
}
const usuario = locals.usuario;
+ const [carrito, compras, favoritos, legales, catalogo] = await Promise.all([
+ leerCarrito(cookies, usuario?.id ?? null),
+ usuario ? comprasDeUsuario(usuario.id) : Promise.resolve([]),
+ usuario ? favoritosDeUsuario(usuario.id) : Promise.resolve([]),
+ indiceLegal(),
+ leerCatalogo()
+ ]);
return {
// Solo lo que la interfaz necesita: nada de fechas internas ni ids de
// sesión viajando al cliente.
usuario: usuario ? { id: usuario.id, email: usuario.email } : null,
- carrito: await leerCarrito(cookies, usuario?.id ?? null),
- compras: usuario ? await comprasDeUsuario(usuario.id) : [],
+ carrito,
+ compras,
// Los favoritos viajan enteros, como el carrito: son unas decenas de
// slugs y cualquier tarjeta necesita saber si el suyo esta dentro.
- favoritos: usuario ? await favoritosDeUsuario(usuario.id) : [],
+ favoritos,
/*
* Con qué proveedores se puede entrar en ESTE servidor. Sale de si hay
* credenciales puestas, que es información del servidor, y lo necesita el
@@ -60,7 +67,7 @@ export async function load({ locals, cookies, url }) {
* viven en la base tienen que bajar por aquí, porque un componente no
* puede consultar.
*/
- legales: await indiceLegal(),
+ legales,
/*
* El catálogo entero, una vez. Hasta ahora viajaba en el paquete de
* JavaScript —lo cargaba `import.meta.glob` al construir— y por eso
@@ -72,6 +79,6 @@ export async function load({ locals, cookies, url }) {
* Son veintiún kilobytes, menos de lo que ocupaba en el paquete. La
* letra completa no va: esa la pide la ficha de cada tema.
*/
- catalogo: await leerCatalogo()
+ catalogo
};
}
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 67903e4..f4b15dc 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -69,7 +69,7 @@
titulo="{CANCIONES_POR_PACK} canciones por un café"
texto="{formatearPrecio(
PRECIO_PACK_CENTIMOS
- )} el pack, en MP3 y con todas sus versiones. En la web suena un fragmento; la descarga es el archivo completo, para llevártelo donde quieras."
+ )} el pack, en MP3 y con todas sus versiones. En la web se escucha la canción completa a calidad reducida; la compra entrega el archivo de mayor calidad."
>
{#snippet acciones()}
Elegir canciones
diff --git a/src/routes/canciones/[slug]/+page.svelte b/src/routes/canciones/[slug]/+page.svelte
index b67860e..55e0391 100644
--- a/src/routes/canciones/[slug]/+page.svelte
+++ b/src/routes/canciones/[slug]/+page.svelte
@@ -168,8 +168,10 @@
{#if cancion.alaVenta}
- En la web suena un fragmento. La descarga completa en MP3, con todas sus versiones, va
- en packs de {CANCIONES_POR_PACK} canciones por {formatearPrecio(PRECIO_PACK_CENTIMOS)}.
+ Escúchala completa aquí a calidad reducida. La compra entrega el archivo de mayor
+ calidad, con todas sus versiones, en packs de {CANCIONES_POR_PACK} canciones por {formatearPrecio(
+ PRECIO_PACK_CENTIMOS
+ )}.
{/if}
@@ -180,7 +182,7 @@
@@ -260,6 +262,17 @@
{#if version.nota}
{version.nota}
{/if}
+ {#if version.interpretes.length > 0}
+
+ {#each version.interpretes as interprete, j (`${interprete.id}-${interprete.rol}`)}
+ {#if j > 0},
+ {/if}{#if interprete.slug}{interprete.nombre} {:else}{interprete.nombre}{/if}
+ {/each}
+
+ {/if}
{version.duracion ? segundosADuracion(version.duracion) : '--:--'}
@@ -496,6 +509,10 @@
font-size: var(--fs-xs);
}
+ .interpretes {
+ font-size: var(--fs-xs);
+ }
+
.duracion {
font-size: var(--fs-sm);
font-variant-numeric: tabular-nums;
diff --git a/src/routes/descargas/[cancion]/[[version]]/+server.ts b/src/routes/descargas/[cancion]/[[version]]/+server.ts
index da39a7c..c620961 100644
--- a/src/routes/descargas/[cancion]/[[version]]/+server.ts
+++ b/src/routes/descargas/[cancion]/[[version]]/+server.ts
@@ -1,6 +1,6 @@
import { error } from '@sveltejs/kit';
import { extname } from 'node:path';
-import { obtenerCancion } from '$lib/server/catalogo';
+import { archivoComprado } from '$lib/server/audios';
import { respuestaDeDescarga } from '$lib/server/medios';
import { tieneCompra } from '$lib/server/pedidos';
import { registrarEntregaIniciada } from '$lib/server/descargas';
@@ -19,34 +19,25 @@ export const GET: RequestHandler = async ({ params, locals, request, getClientAd
error(401, 'Entra en tu cuenta para descargar este tema.');
}
- const cancion = await obtenerCancion(params.cancion);
- if (!cancion) error(404, 'Ese tema no existe.');
+ const archivo = await archivoComprado(params.cancion, params.version);
+ if (!archivo) error(404, 'Ese tema, versión o archivo no existe.');
- if (!(await tieneCompra(locals.usuario.id, cancion.slug))) {
+ if (!(await tieneCompra(locals.usuario.id, archivo.principalSlug))) {
error(403, 'Este tema no está entre tus compras.');
}
// Una versión alternativa va incluida en la compra del tema: quien lo ha
// comprado se lleva todos sus arreglos.
- const version = params.version
- ? cancion.versiones.find((v) => v.id === params.version)
- : undefined;
+ const nombre = archivo.versionNombre
+ ? `${archivo.titulo} (${archivo.versionNombre})${extname(archivo.clave)}`
+ : `${archivo.titulo}${extname(archivo.clave)}`;
- if (params.version && !version) error(404, 'Esa versión no existe.');
-
- const clave = version?.audio ?? cancion.audio;
- if (!clave) error(404, 'Este tema todavía no tiene archivo descargable.');
-
- const nombre = version
- ? `${cancion.titulo} (${version.nombre})${extname(clave)}`
- : `${cancion.titulo}${extname(clave)}`;
-
- const respuesta = await respuestaDeDescarga(clave, nombre);
+ const respuesta = await respuestaDeDescarga(archivo.clave, nombre);
if (!respuesta) error(404, 'El archivo no está disponible ahora mismo.');
await registrarEntregaIniciada({
usuarioId: locals.usuario.id,
- cancionSlug: cancion.slug,
+ cancionId: archivo.cancionId,
ip: getClientAddress(),
agente: request.headers.get('user-agent')
});
diff --git a/src/routes/interpretes/+page.server.ts b/src/routes/interpretes/+page.server.ts
new file mode 100644
index 0000000..dc7c2c8
--- /dev/null
+++ b/src/routes/interpretes/+page.server.ts
@@ -0,0 +1,5 @@
+import { artistasPublicos } from '$lib/server/artistas';
+
+export async function load() {
+ return { artistas: await artistasPublicos() };
+}
diff --git a/src/routes/interpretes/+page.svelte b/src/routes/interpretes/+page.svelte
new file mode 100644
index 0000000..c6aae46
--- /dev/null
+++ b/src/routes/interpretes/+page.svelte
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+{#if data.artistas.length === 0}
+ Aún no hay intérpretes publicados.
+{/if}
+
+
diff --git a/src/routes/interpretes/[slug]/+page.server.ts b/src/routes/interpretes/[slug]/+page.server.ts
new file mode 100644
index 0000000..92c1242
--- /dev/null
+++ b/src/routes/interpretes/[slug]/+page.server.ts
@@ -0,0 +1,8 @@
+import { error } from '@sveltejs/kit';
+import { obtenerArtistaPublico } from '$lib/server/artistas';
+
+export async function load({ params }) {
+ const artista = await obtenerArtistaPublico(params.slug);
+ if (!artista) error(404, 'Ese intérprete no existe.');
+ return { artista };
+}
diff --git a/src/routes/interpretes/[slug]/+page.svelte b/src/routes/interpretes/[slug]/+page.svelte
new file mode 100644
index 0000000..e981bab
--- /dev/null
+++ b/src/routes/interpretes/[slug]/+page.svelte
@@ -0,0 +1,122 @@
+
+
+
+
+
+ {#if data.artista.imagen}
+
+ {/if}
+
+
{data.artista.tipo} · {data.artista.codigo}
+
{data.artista.nombre}
+ {#if data.artista.descripcion}
{data.artista.descripcion}
{/if}
+
+ {[data.artista.lugarOrigen, data.artista.pais, periodo].filter(Boolean).join(' · ')}
+
+ {#if data.artista.sitioWeb}
+
Sitio oficial
+ {/if}
+
+
+
+{#if data.artista.biografia}
+
+
+ {@html data.artista.biografia}
+{/if}
+
+
+ Discografía
+ {#if data.artista.canciones.length > 0}
+
+ {:else}
+ No hay grabaciones publicadas todavía.
+ {/if}
+
+
+{#if data.artista.identificadores.length > 0}
+
+ {#each data.artista.identificadores as identificador (identificador.sistema)}
+ {identificador.sistema}
+ {identificador.valor}
+ {/each}
+
+{/if}
+
+
diff --git a/src/routes/musica/+page.svelte b/src/routes/musica/+page.svelte
index ac30afe..a904831 100644
--- a/src/routes/musica/+page.svelte
+++ b/src/routes/musica/+page.svelte
@@ -31,7 +31,7 @@
String(cancion.ano ?? ''),
...cancion.etiquetas,
...cancion.generos.map((g) => g.nombre),
- ...cancion.interpretes
+ ...cancion.interpretes.map((i) => i.nombre)
].join(' ')
)
}))
diff --git a/src/routes/sitemap.xml/+server.ts b/src/routes/sitemap.xml/+server.ts
index 601bfac..ce9f0ba 100644
--- a/src/routes/sitemap.xml/+server.ts
+++ b/src/routes/sitemap.xml/+server.ts
@@ -3,6 +3,7 @@ import { entradasPublicadas, paginasPublicadas } from '$lib/server/editorial';
import { site } from '$lib/site';
import { indiceDelTaller } from '$lib/server/taller';
import { indiceLegal } from '$lib/server/legal';
+import { artistasPublicos } from '$lib/server/artistas';
import type { RequestHandler } from './$types';
/**
@@ -44,7 +45,8 @@ export const GET: RequestHandler = async () => {
discos,
temas,
entradas,
- paginas
+ paginas,
+ artistas
] = await Promise.all([
indiceDelTaller(),
indiceLegal(),
@@ -52,12 +54,14 @@ export const GET: RequestHandler = async () => {
slugsDeAlbum(),
etiquetas(),
entradasPublicadas(),
- paginasPublicadas()
+ paginasPublicadas(),
+ artistasPublicos()
]);
const rutas = [
url('/', PRIORIDAD.portada),
url('/musica', PRIORIDAD.seccion),
+ url('/interpretes', PRIORIDAD.seccion),
url('/taller', PRIORIDAD.seccion),
url('/blog', PRIORIDAD.seccion),
url('/etiquetas', PRIORIDAD.resto),
@@ -68,6 +72,7 @@ export const GET: RequestHandler = async () => {
// Incluye los álbumes de singles, que son sintéticos pero tienen página.
...discos.map((slug) => url(`/albumes/${slug}`, PRIORIDAD.obra)),
...canciones.map((c) => url(`/canciones/${c.slug}`, PRIORIDAD.obra)),
+ ...artistas.map((a) => url(`/interpretes/${a.slug}`, PRIORIDAD.obra)),
url('/generos', PRIORIDAD.seccion),
url('/generos/glosario', PRIORIDAD.resto),
url('/generos/letristas', PRIORIDAD.resto),
diff --git a/static/escucha/como-si-nada/01-como-si-nada-maqueta.mp3 b/static/escucha/como-si-nada/01-como-si-nada-maqueta.mp3
new file mode 100644
index 0000000..fc9419e
Binary files /dev/null and b/static/escucha/como-si-nada/01-como-si-nada-maqueta.mp3 differ
diff --git a/static/escucha/como-si-nada/01-como-si-nada-orquestal.mp3 b/static/escucha/como-si-nada/01-como-si-nada-orquestal.mp3
new file mode 100644
index 0000000..cd7b789
Binary files /dev/null and b/static/escucha/como-si-nada/01-como-si-nada-orquestal.mp3 differ
diff --git a/static/escucha/como-si-nada/01-como-si-nada.mp3 b/static/escucha/como-si-nada/01-como-si-nada.mp3
new file mode 100644
index 0000000..e157185
Binary files /dev/null and b/static/escucha/como-si-nada/01-como-si-nada.mp3 differ
diff --git a/static/escucha/como-si-nada/02-media-verdad.mp3 b/static/escucha/como-si-nada/02-media-verdad.mp3
new file mode 100644
index 0000000..408a545
Binary files /dev/null and b/static/escucha/como-si-nada/02-media-verdad.mp3 differ
diff --git a/static/escucha/como-si-nada/03-el-ultimo-tren-duo.mp3 b/static/escucha/como-si-nada/03-el-ultimo-tren-duo.mp3
new file mode 100644
index 0000000..355f7cc
Binary files /dev/null and b/static/escucha/como-si-nada/03-el-ultimo-tren-duo.mp3 differ
diff --git a/static/escucha/como-si-nada/03-el-ultimo-tren.mp3 b/static/escucha/como-si-nada/03-el-ultimo-tren.mp3
new file mode 100644
index 0000000..6e17ebf
Binary files /dev/null and b/static/escucha/como-si-nada/03-el-ultimo-tren.mp3 differ
diff --git a/static/escucha/como-si-nada/04-domingo-largo.mp3 b/static/escucha/como-si-nada/04-domingo-largo.mp3
new file mode 100644
index 0000000..aa5593f
Binary files /dev/null and b/static/escucha/como-si-nada/04-domingo-largo.mp3 differ
diff --git a/static/escucha/dos-orillas/01-dos-orillas.mp3 b/static/escucha/dos-orillas/01-dos-orillas.mp3
new file mode 100644
index 0000000..1506682
Binary files /dev/null and b/static/escucha/dos-orillas/01-dos-orillas.mp3 differ
diff --git a/static/escucha/dos-orillas/02-carta-sin-enviar.mp3 b/static/escucha/dos-orillas/02-carta-sin-enviar.mp3
new file mode 100644
index 0000000..ee4073b
Binary files /dev/null and b/static/escucha/dos-orillas/02-carta-sin-enviar.mp3 differ
diff --git a/static/escucha/dos-orillas/03-el-invierno-que-viene.mp3 b/static/escucha/dos-orillas/03-el-invierno-que-viene.mp3
new file mode 100644
index 0000000..66e5594
Binary files /dev/null and b/static/escucha/dos-orillas/03-el-invierno-que-viene.mp3 differ
diff --git a/static/escucha/preludios-para-piano/01-preludio-i-cuarteto.mp3 b/static/escucha/preludios-para-piano/01-preludio-i-cuarteto.mp3
new file mode 100644
index 0000000..7eb6024
Binary files /dev/null and b/static/escucha/preludios-para-piano/01-preludio-i-cuarteto.mp3 differ
diff --git a/static/escucha/preludios-para-piano/01-preludio-i.mp3 b/static/escucha/preludios-para-piano/01-preludio-i.mp3
new file mode 100644
index 0000000..fc9419e
Binary files /dev/null and b/static/escucha/preludios-para-piano/01-preludio-i.mp3 differ
diff --git a/static/escucha/preludios-para-piano/02-preludio-ii.mp3 b/static/escucha/preludios-para-piano/02-preludio-ii.mp3
new file mode 100644
index 0000000..cd7b789
Binary files /dev/null and b/static/escucha/preludios-para-piano/02-preludio-ii.mp3 differ
diff --git a/static/escucha/preludios-para-piano/03-preludio-iii.mp3 b/static/escucha/preludios-para-piano/03-preludio-iii.mp3
new file mode 100644
index 0000000..e157185
Binary files /dev/null and b/static/escucha/preludios-para-piano/03-preludio-iii.mp3 differ
diff --git a/static/escucha/ruido-blanco/01-ruido-blanco.mp3 b/static/escucha/ruido-blanco/01-ruido-blanco.mp3
new file mode 100644
index 0000000..408a545
Binary files /dev/null and b/static/escucha/ruido-blanco/01-ruido-blanco.mp3 differ
diff --git a/static/escucha/ruido-blanco/02-nadie-mira.mp3 b/static/escucha/ruido-blanco/02-nadie-mira.mp3
new file mode 100644
index 0000000..355f7cc
Binary files /dev/null and b/static/escucha/ruido-blanco/02-nadie-mira.mp3 differ
diff --git a/static/escucha/ruido-blanco/03-cinco-de-la-manana.mp3 b/static/escucha/ruido-blanco/03-cinco-de-la-manana.mp3
new file mode 100644
index 0000000..6e17ebf
Binary files /dev/null and b/static/escucha/ruido-blanco/03-cinco-de-la-manana.mp3 differ
diff --git a/static/escucha/singles/dorina.mp3 b/static/escucha/singles/dorina.mp3
new file mode 100644
index 0000000..ef3aa34
Binary files /dev/null and b/static/escucha/singles/dorina.mp3 differ
diff --git a/static/escucha/singles/la-ultima-carta.mp3 b/static/escucha/singles/la-ultima-carta.mp3
new file mode 100644
index 0000000..aa5593f
Binary files /dev/null and b/static/escucha/singles/la-ultima-carta.mp3 differ
diff --git a/static/escucha/singles/tres-de-la-tarde.mp3 b/static/escucha/singles/tres-de-la-tarde.mp3
new file mode 100644
index 0000000..1506682
Binary files /dev/null and b/static/escucha/singles/tres-de-la-tarde.mp3 differ
diff --git a/static/escucha/singles/verano-tarde-acustica.mp3 b/static/escucha/singles/verano-tarde-acustica.mp3
new file mode 100644
index 0000000..ee4073b
Binary files /dev/null and b/static/escucha/singles/verano-tarde-acustica.mp3 differ
diff --git a/static/escucha/singles/verano-tarde.mp3 b/static/escucha/singles/verano-tarde.mp3
new file mode 100644
index 0000000..66e5594
Binary files /dev/null and b/static/escucha/singles/verano-tarde.mp3 differ