From 54df82005680c147cde6a48e98a86f317cce1739 Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 8 Sep 2026 16:58:11 +0200 Subject: [PATCH] =?UTF-8?q?Vuelca=20el=20cat=C3=A1logo=20a=20PostgreSQL,?= =?UTF-8?q?=20y=20lo=20comprueba?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Los 48 archivos entran en la base: 18 canciones con sus 5 versiones como filas hermanas, 4 discos, 4 estilos, 8 géneros, 14 capítulos, 9 personas, 53 etiquetas, 2 entradas, 5 legales y una página. La web sigue leyendo de los archivos; esto solo llena el sitio donde caben. Reutiliza los analizadores del sitio en vez de leer el frontmatter otra vez. Es la decisión que sostiene todo lo demás: si un valor por defecto o una normalización cambian, cambian para los dos. Un segundo analizador «parecido» es lo que garantiza que un día la base y la web cuenten cosas distintas sin que nadie lo note. Todo en una transacción, y al final comprueba lo escrito contra lo leído —la letra de cada tema carácter a carácter— porque «no dio error» no es lo mismo que «está bien». Si no cuadra, deshace y dice qué falló. Y es idempotente: se puede lanzar las veces que haga falta sin duplicar nada, sin tocar cuentas, pedidos ni compras. Para poder reutilizar ese código desde Node hizo falta un gancho de resolución —`$lib`, imports sin extensión y un sustituto de `$app/paths`— y quitar una propiedad de parámetro de `ErrorDeContenido`: es sintaxis exclusiva de TypeScript y ningún cargador que solo borre tipos puede con ella. Y una corrección: el cuerpo del Markdown de una canción NO era un comentario, es la letra. Lo dije al revés en el documento del modelo y lo repetí varias veces. El campo `letra:` del frontmatter —que aparece en un solo archivo— son los créditos de quién la firma. Corregido en el documento, en el esquema, y quitada la columna `nota` que sobraba. Co-Authored-By: Claude Opus 5 (1M context) --- docs/modelo-de-datos.md | 14 +- drizzle/0004_letra_es_el_cuerpo.sql | 1 + drizzle/meta/0004_snapshot.json | 5695 ++++++++++++++++++++++++++ drizzle/meta/_journal.json | 7 + package-lock.json | 10 +- package.json | 4 +- scripts/db/app-paths.mjs | 12 + scripts/db/gancho-lib.mjs | 57 + scripts/db/resolver-lib.mjs | 16 + scripts/db/volcar.mjs | 643 +++ src/lib/content/fields.ts | 19 +- src/lib/server/db/schema/catalogo.ts | 21 +- 12 files changed, 6482 insertions(+), 17 deletions(-) create mode 100644 drizzle/0004_letra_es_el_cuerpo.sql create mode 100644 drizzle/meta/0004_snapshot.json create mode 100644 scripts/db/app-paths.mjs create mode 100644 scripts/db/gancho-lib.mjs create mode 100644 scripts/db/resolver-lib.mjs create mode 100644 scripts/db/volcar.mjs diff --git a/docs/modelo-de-datos.md b/docs/modelo-de-datos.md index 354902f..79822b1 100644 --- a/docs/modelo-de-datos.md +++ b/docs/modelo-de-datos.md @@ -13,9 +13,17 @@ para leerse. Cuando se implemente, la verdad pasa a ser ## Por qué Lo que hay hoy en `src/content/**` son registros disfrazados de documento: una -canción tiene veinte campos estructurados en YAML —`registro`, `duracion`, -`interpretes`, `versiones`, `videos`, `etiquetas`— y la letra entera también va -en el frontmatter. El cuerpo en Markdown son cuatro líneas de comentario. +canción tiene **veintiún campos estructurados en YAML** —`registro`, `duracion`, +`interpretes`, `versiones`, `videos`, `etiquetas`…— y el archivo entero existe +para sostenerlos. + +> **Corrección.** Una versión anterior de este documento decía que la letra +> también iba en el frontmatter y que el cuerpo del Markdown eran cuatro líneas +> de comentario. **Es al revés**: el cuerpo del Markdown es la letra, y el campo +> `letra:` —que aparece en un solo archivo— son los créditos de quién la firma. +> Se vio al escribir el volcado. No cambia la conclusión, pero sí el reparto: la +> letra es prosa legítima y se queda como texto; lo que no debía estar en YAML +> son los otros veintiún campos. Dos hallazgos concretos, no cuestión de gusto: diff --git a/drizzle/0004_letra_es_el_cuerpo.sql b/drizzle/0004_letra_es_el_cuerpo.sql new file mode 100644 index 0000000..b505469 --- /dev/null +++ b/drizzle/0004_letra_es_el_cuerpo.sql @@ -0,0 +1 @@ +ALTER TABLE "cancion" DROP COLUMN "nota"; \ No newline at end of file diff --git a/drizzle/meta/0004_snapshot.json b/drizzle/meta/0004_snapshot.json new file mode 100644 index 0000000..821b788 --- /dev/null +++ b/drizzle/meta/0004_snapshot.json @@ -0,0 +1,5695 @@ +{ + "id": "63e52146-24ce-46df-a73e-d8916385dc0f", + "prevId": "bf0caf39-1bac-491b-aaeb-ee42d57d7f58", + "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'" + }, + "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.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": "''" + }, + "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 + }, + "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_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, + "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": {} + } + }, + "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": {}, + "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 + } + }, + "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_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": "''" + }, + "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 + }, + "enlace": { + "name": "enlace", + "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_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 + }, + "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_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_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.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_slug": { + "name": "cancion_slug", + "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" + } + }, + "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 + }, + "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": { + "name": "carrito_usuario", + "columns": [ + { + "expression": "usuario_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "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_slug": { + "name": "cancion_slug", + "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" + } + }, + "compositePrimaryKeys": { + "carrito_item_carrito_id_cancion_slug_pk": { + "name": "carrito_item_carrito_id_cancion_slug_pk", + "columns": [ + "carrito_id", + "cancion_slug" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.compra": { + "name": "compra", + "schema": "", + "columns": { + "usuario_id": { + "name": "usuario_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cancion_slug": { + "name": "cancion_slug", + "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_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_slug_pk": { + "name": "compra_usuario_id_cancion_slug_pk", + "columns": [ + "usuario_id", + "cancion_slug" + ] + } + }, + "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_slug": { + "name": "cancion_slug", + "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" + } + }, + "compositePrimaryKeys": { + "pedido_item_pedido_id_cancion_slug_pk": { + "name": "pedido_item_pedido_id_cancion_slug_pk", + "columns": [ + "pedido_id", + "cancion_slug" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.favorito": { + "name": "favorito", + "schema": "", + "columns": { + "usuario_id": { + "name": "usuario_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "cancion_slug": { + "name": "cancion_slug", + "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" + } + }, + "compositePrimaryKeys": { + "favorito_usuario_id_cancion_slug_pk": { + "name": "favorito_usuario_id_cancion_slug_pk", + "columns": [ + "usuario_id", + "cancion_slug" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.reproduccion": { + "name": "reproduccion", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "cancion_slug": { + "name": "cancion_slug", + "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_slug", + "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_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_slug": { + "name": "cancion_slug", + "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_slug", + "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" + } + }, + "compositePrimaryKeys": { + "valoracion_usuario_id_cancion_slug_pk": { + "name": "valoracion_usuario_id_cancion_slug_pk", + "columns": [ + "usuario_id", + "cancion_slug" + ] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "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 30f725a..0732370 100644 --- a/drizzle/meta/_journal.json +++ b/drizzle/meta/_journal.json @@ -29,6 +29,13 @@ "when": 1788878096657, "tag": "0003_valores_por_defecto", "breakpoints": true + }, + { + "idx": 4, + "version": "7", + "when": 1788879010816, + "tag": "0004_letra_es_el_cuerpo", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4db3120..5837dd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.63.0", "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@types/js-yaml": "^4.0.9", "@types/node": "^22", "@types/pg": "^8.23.1", "@vitest/browser-playwright": "^4.1.8", @@ -2197,6 +2198,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -6248,7 +6256,7 @@ "version": "8.21.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index 08815ce..1fb1338 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "predev": "node scripts/medios.mjs", "prebuild": "node scripts/medios.mjs", "db:guardas": "node --env-file=.env scripts/db/comprobar-guardas.mjs", - "db:probar": "node --env-file=.env scripts/db/probar-migracion.mjs" + "db:probar": "node --env-file=.env scripts/db/probar-migracion.mjs", + "db:volcar": "node --experimental-strip-types --import ./scripts/db/resolver-lib.mjs --env-file=.env scripts/db/volcar.mjs" }, "devDependencies": { "@eslint/js": "^10.0.1", @@ -31,6 +32,7 @@ "@sveltejs/adapter-node": "^5.5.4", "@sveltejs/kit": "^2.63.0", "@sveltejs/vite-plugin-svelte": "^7.1.2", + "@types/js-yaml": "^4.0.9", "@types/node": "^22", "@types/pg": "^8.23.1", "@vitest/browser-playwright": "^4.1.8", diff --git a/scripts/db/app-paths.mjs b/scripts/db/app-paths.mjs new file mode 100644 index 0000000..7444f62 --- /dev/null +++ b/scripts/db/app-paths.mjs @@ -0,0 +1,12 @@ +/** + * Sustituto de `$app/paths` para los scripts. + * + * `site.ts` lo usa para componer las direcciones de la navegación, y el volcado + * solo necesita de ese archivo el nombre del artista —la autoría por defecto de + * cada canción—. Sin base configurada, `resolve` es la identidad, que es + * exactamente lo que hace SvelteKit cuando el sitio vive en la raíz de su + * dominio, como este. + */ +export const resolve = (ruta) => ruta; +export const base = ''; +export const assets = ''; diff --git a/scripts/db/gancho-lib.mjs b/scripts/db/gancho-lib.mjs new file mode 100644 index 0000000..3ba249f --- /dev/null +++ b/scripts/db/gancho-lib.mjs @@ -0,0 +1,57 @@ +/** + * El gancho de resolución para poder cargar código del sitio desde un script. + * + * Hace dos cosas que Vite hace y Node no: + * + * - `$lib/x` pasa a ser `src/lib/x`. + * - Los imports sin extensión —`./fields`, `$lib/utils/date`— encuentran su + * `.ts`. En ESM, Node exige la ruta completa; el código del proyecto se + * escribe como se escribe con un empaquetador delante. + * + * Existe para que el volcado pueda reutilizar los analizadores del sitio en + * lugar de copiarlos. Una copia «parecida» es lo que garantiza que un día la + * base y la web cuenten cosas distintas y nadie lo note. + */ + +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const RAIZ_LIB = path.resolve('src/lib'); + +/** + * Los módulos que SvelteKit inyecta en tiempo de compilación y fuera de la + * aplicación no existen. Se sustituyen por lo mínimo que necesita el código que + * el volcado reutiliza; `$app/types` no aparece porque solo se importa como + * tipo y el borrado de tipos se lo lleva por delante. + */ +const SUSTITUTOS = { + '$app/paths': path.resolve('scripts/db/app-paths.mjs') +}; + +/** Prueba el archivo tal cual, con extensión, y como carpeta con índice. */ +function primeroQueExista(base) { + const candidatos = [base, `${base}.ts`, `${base}.js`, `${base}.mjs`, path.join(base, 'index.ts')]; + return candidatos.find((c) => fs.existsSync(c) && fs.statSync(c).isFile()); +} + +export function resolve(especificador, contexto, siguiente) { + if (SUSTITUTOS[especificador]) { + return { url: pathToFileURL(SUSTITUTOS[especificador]).href, shortCircuit: true }; + } + + if (especificador.startsWith('$lib/')) { + const encontrado = primeroQueExista(path.join(RAIZ_LIB, especificador.slice(5))); + if (!encontrado) throw new Error(`No encuentro ${especificador}`); + return { url: pathToFileURL(encontrado).href, shortCircuit: true }; + } + + // Relativo y sin extensión: se completa igual que haría el empaquetador. + if (especificador.startsWith('.') && !path.extname(especificador) && contexto.parentURL) { + const desde = path.dirname(fileURLToPath(contexto.parentURL)); + const encontrado = primeroQueExista(path.resolve(desde, especificador)); + if (encontrado) return { url: pathToFileURL(encontrado).href, shortCircuit: true }; + } + + return siguiente(especificador, contexto); +} diff --git a/scripts/db/resolver-lib.mjs b/scripts/db/resolver-lib.mjs new file mode 100644 index 0000000..4fc77f3 --- /dev/null +++ b/scripts/db/resolver-lib.mjs @@ -0,0 +1,16 @@ +/** + * Enseña a Node lo que significa `$lib/…`. + * + * Los analizadores de contenido son código del sitio y usan el alias que + * resuelve Vite. El volcado los reutiliza a propósito —para que lo escrito en + * la base no pueda diferir de lo que enseña la web—, así que hay que darle a + * Node la misma equivalencia en vez de copiar los analizadores, que es lo que + * garantizaría que un día dejen de coincidir. + * + * Se engancha con `--import ./scripts/db/resolver-lib.mjs`. + */ + +import { register } from 'node:module'; +import { pathToFileURL } from 'node:url'; + +register('./gancho-lib.mjs', pathToFileURL('./scripts/db/')); diff --git a/scripts/db/volcar.mjs b/scripts/db/volcar.mjs new file mode 100644 index 0000000..d7a6240 --- /dev/null +++ b/scripts/db/volcar.mjs @@ -0,0 +1,643 @@ +/** + * Vuelca el contenido de `src/content/**` a PostgreSQL. + * + * npm run db:volcar # vuelca y comprueba + * npm run db:volcar -- --seco # solo dice qué haría + * + * ## Por qué reutiliza los analizadores del sitio + * + * En vez de volver a leer el frontmatter a mi manera, este script pasa cada + * archivo por `src/lib/content/schema.ts`, que es exactamente lo que hace la + * web hoy. Así lo volcado no puede diferir de lo que se ve: si un valor por + * defecto o una normalización cambian, cambian para los dos. Escribir un + * segundo analizador «parecido» es la forma más fácil de que la base y la web + * cuenten cosas distintas y nadie lo note. + * + * ## Es idempotente + * + * Se puede lanzar las veces que haga falta. Borra lo volcado antes de volver a + * escribirlo, y no toca nada de lo que generan las personas —cuentas, pedidos, + * compras—: esas tablas ni se miran. + * + * ## Todo en una transacción + * + * Si algo falla a mitad, no queda medio catálogo dentro. Y al final comprueba + * que lo escrito coincide con lo leído, porque «no dio error» no es lo mismo + * que «está bien». + */ + +import { createHash } from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; +// Con nombre y no por defecto: js-yaml 4 es CommonJS y su interoperabilidad +// con modulos no expone un `default`. +import { load as leerYaml } from 'js-yaml'; +import pg from 'pg'; + +import { + parsearAlbum, + parsearCancion, + parsearCapitulo, + parsearEntrada, + parsearEstilo, + parsearLegal, + parsearPagina +} from '../../src/lib/content/schema.ts'; +import { extraerLineas } from '../../src/lib/content/extracto.ts'; + +const SECO = process.argv.includes('--seco'); +const RAIZ = 'src/content'; + +/* ------------------------------------------------------------------------- + * Leer los archivos + * ---------------------------------------------------------------------- */ + +/** Separa el frontmatter del cuerpo. */ +function partir(texto) { + const lineas = texto.split(/\r?\n/); + if (lineas[0]?.trim() !== '---') return { datos: {}, cuerpo: texto.trim() }; + + const cierre = lineas.indexOf('---', 1); + if (cierre === -1) return { datos: {}, cuerpo: texto.trim() }; + + return { + datos: leerYaml(lineas.slice(1, cierre).join('\n')) ?? {}, + cuerpo: lineas + .slice(cierre + 1) + .join('\n') + .trim() + }; +} + +function leerCarpeta(carpeta, parser) { + const dir = path.join(RAIZ, carpeta); + if (!fs.existsSync(dir)) return []; + + return fs + .readdirSync(dir) + .filter((n) => n.endsWith('.md')) + .sort() + .map((nombre) => { + const ruta = path.join(dir, nombre); + const { datos, cuerpo } = partir(fs.readFileSync(ruta, 'utf8')); + const slug = nombre.replace(/\.md$/, ''); + return { slug, cuerpo, ruta, datos: parser(datos, slug, ruta) }; + }); +} + +/* ------------------------------------------------------------------------- + * Escribir + * ---------------------------------------------------------------------- */ + +const nuevoId = () => crypto.randomUUID(); + +/** Normaliza una etiqueta a slug, como hace el sitio. */ +const slugificar = (nombre) => + nombre + .toLowerCase() + .normalize('NFD') + .replace(/[̀-ͯ]/g, '') + .replace(/[^a-z0-9]+/g, '-') + .replace(/^-+|-+$/g, ''); + +async function volcar(c, contenido, informe) { + const { estilos, albumes, canciones, capitulos, entradas, legales, paginas } = contenido; + + /* --- Se borra lo volcado antes de reescribirlo ----------------------- + * + * En orden inverso a las dependencias. Las tablas de cuentas, pedidos y + * compras no aparecen aquí ni por asomo: esas las llenan las personas. + */ + const aVaciar = [ + 'capitulo_acepcion', + 'genero_tema', + 'cancion_genero', + 'genero_seccion', + 'genero_alias', + 'genero_pais', + 'genero_origen', + 'genero_metro', + 'genero_compas', + 'genero_instrumento', + 'genero_persona', + 'obra_referencia_persona', + 'obra_referencia', + 'capitulo', + 'genero', + 'entrada_cancion', + 'entrada_etiqueta', + 'entrada', + 'version_legal', + 'documento_legal', + 'pagina', + 'autoria', + 'registro_obra', + 'cancion_persona', + 'cancion_enlace', + 'cancion_etiqueta', + 'traduccion', + 'video', + 'cancion', + 'album_enlace', + 'credito_album', + 'album', + 'etiqueta', + 'estilo', + 'persona' + ]; + for (const tabla of aVaciar) await c.query(`DELETE FROM "${tabla}"`); + + /* --- Personas --------------------------------------------------------- + * + * Salen de los créditos, que hoy son cadenas sueltas repetidas en cada + * archivo. Aquí se unifican por nombre: es justo lo que la tabla existe + * para arreglar. + */ + const personas = new Map(); + const persona = async (nombre) => { + const limpio = nombre.trim(); + if (personas.has(limpio)) return personas.get(limpio); + const id = nuevoId(); + await c.query('INSERT INTO persona (id, slug, nombre, estado) VALUES ($1, $2, $3, $4)', [ + id, + slugificar(limpio), + limpio, + 'publicado' + ]); + personas.set(limpio, id); + return id; + }; + + /* --- Etiquetas ------------------------------------------------------- */ + const etiquetas = new Map(); + const etiqueta = async (nombre) => { + const slug = slugificar(nombre); + if (etiquetas.has(slug)) return etiquetas.get(slug); + const id = nuevoId(); + await c.query('INSERT INTO etiqueta (id, slug, nombre) VALUES ($1, $2, $3)', [ + id, + slug, + nombre.trim() + ]); + etiquetas.set(slug, id); + return id; + }; + + /* --- Estilos ---------------------------------------------------------- */ + const idEstilo = new Map(); + for (const { datos } of estilos) { + const id = nuevoId(); + await c.query( + `INSERT INTO estilo (id, slug, nombre, resumen, orden, principal, estado) + VALUES ($1, $2, $3, $4, $5, $6, 'publicado')`, + [id, datos.slug, datos.nombre, datos.resumen, datos.orden, datos.principal] + ); + idEstilo.set(datos.slug, id); + } + informe.estilo = estilos.length; + + /* --- Álbumes ----------------------------------------------------------- */ + const idAlbum = new Map(); + for (const { datos } of albumes) { + const id = nuevoId(); + await c.query( + `INSERT INTO album (id, slug, titulo, estilo_id, tipo, fecha, sello, resumen, + destacado, numero_catalogo, formatos, estado) + VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,'publicado')`, + [ + id, + datos.slug, + datos.titulo, + idEstilo.get(datos.estilo), + datos.tipo, + datos.fecha, + datos.sello ?? null, + datos.resumen, + datos.destacado, + datos.edicion?.numeroCatalogo ?? null, + datos.edicion?.formatos?.length ? datos.edicion.formatos : null + ] + ); + idAlbum.set(datos.slug, id); + + for (const [plataforma, url] of Object.entries(datos.enlaces ?? {})) { + await c.query('INSERT INTO album_enlace (album_id, plataforma, url) VALUES ($1,$2,$3)', [ + id, + plataforma, + url + ]); + } + for (const [i, credito] of (datos.edicion?.creditos ?? []).entries()) { + await c.query( + `INSERT INTO credito_album (id, album_id, persona_id, nombre, rol, orden) + VALUES ($1,$2,$3,$4,$5,$6)`, + [nuevoId(), id, await persona(credito.nombre), credito.nombre, credito.rol, i] + ); + } + } + informe.album = albumes.length; + + /* --- Canciones, y sus versiones como filas hermanas -------------------- */ + let versiones = 0; + for (const { datos, cuerpo } of canciones) { + const id = nuevoId(); + await c.query( + `INSERT INTO cancion (id, slug, titulo, estilo_id, album_id, numero, duracion_s, ano, + letra, idioma, inspiracion, instrumental, destacada, ala_venta, estado) + VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,'publicado')`, + [ + id, + datos.slug, + datos.titulo, + idEstilo.get(datos.estilo), + datos.album ? (idAlbum.get(datos.album) ?? null) : null, + datos.numero, + datos.duracion ?? null, + datos.ano ?? null, + cuerpo || null, + datos.idioma, + datos.inspiracion?.length ? datos.inspiracion.join('\n\n') : null, + datos.instrumental, + datos.destacada, + datos.alaVenta + ] + ); + + /* Créditos: letra, música e intérpretes. */ + for (const [rol, nombres] of [ + ['letra', datos.letra], + ['musica', datos.musica], + ['interprete', datos.interpretes] + ]) { + for (const [i, nombre] of (nombres ?? []).entries()) { + await c.query( + `INSERT INTO cancion_persona (cancion_id, persona_id, rol, orden) + VALUES ($1,$2,$3,$4) ON CONFLICT DO NOTHING`, + [id, await persona(nombre), rol, i] + ); + } + } + + for (const nombre of datos.etiquetas ?? []) { + await c.query( + `INSERT INTO cancion_etiqueta (cancion_id, etiqueta_id) VALUES ($1,$2) + ON CONFLICT DO NOTHING`, + [id, await etiqueta(nombre)] + ); + } + + for (const [plataforma, url] of Object.entries(datos.enlaces ?? {})) { + await c.query('INSERT INTO cancion_enlace (cancion_id, plataforma, url) VALUES ($1,$2,$3)', [ + id, + plataforma, + url + ]); + } + + for (const [i, v] of (datos.videos ?? []).entries()) { + await c.query( + 'INSERT INTO video (id, cancion_id, youtube_id, titulo, orden) VALUES ($1,$2,$3,$4,$5)', + [nuevoId(), id, v.youtube, v.titulo, i] + ); + } + + if (datos.traduccion) { + await c.query('INSERT INTO traduccion (cancion_id, idioma, texto) VALUES ($1,$2,$3)', [ + id, + 'es', + datos.traduccion + ]); + } + + const r = datos.registro ?? {}; + if (r.iswc || r.isrc || r.entidad || r.numero || r.editorial) { + await c.query( + `INSERT INTO registro_obra (cancion_id, iswc, isrc, entidad, numero, editorial) + VALUES ($1,$2,$3,$4,$5,$6)`, + [ + id, + r.iswc ?? null, + r.isrc ?? null, + r.entidad ?? null, + r.numero ?? null, + r.editorial ?? null + ] + ); + } + for (const parte of r.reparto ?? []) { + await c.query( + `INSERT INTO autoria (cancion_id, persona_id, rol, porcentaje) VALUES ($1,$2,$3,$4) + ON CONFLICT DO NOTHING`, + [id, await persona(parte.nombre), parte.rol, parte.porcentaje] + ); + } + + /* + * Las versiones pasan a ser filas hermanas, con los campos COPIADOS de la + * principal. No se heredan al leer: un nulo heredado nunca se sabe si es + * «no lo sé» o «lo mismo de arriba». + */ + for (const [i, v] of (datos.versiones ?? []).entries()) { + 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')`, + [ + nuevoId(), + `${datos.slug}-${v.id}`, + datos.titulo, + idEstilo.get(datos.estilo), + id, + v.nombre, + i, + v.duracion ?? null, + datos.ano ?? null, + cuerpo || null, + datos.idioma, + datos.instrumental + ] + ); + versiones++; + } + } + informe.cancion = canciones.length; + informe.version = versiones; + + /* --- Taller: géneros y capítulos --------------------------------------- + * + * Cada ficha del taller da un `genero` y un `capitulo` que lo describe. Los + * campos comparables se quedan de momento en las notas en prosa: pasarlos a + * `metro` y `compas` exige decidir a mano a qué fila corresponde cada frase, + * y eso no lo puede adivinar un volcado. + */ + const idGenero = new Map(); + for (const { datos } of capitulos.filter((c) => c.datos.tipo === 'ficha')) { + const id = nuevoId(); + const f = datos.ficha; + await c.query( + `INSERT INTO genero (id, slug, nombre, resumen, origen_lugar, tempo, rima, + metrica_nota, compas_nota, rasgos, estado, origen) + VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,'publicado','manual')`, + [ + id, + datos.slug, + datos.titulo, + datos.resumen, + f.origen ?? null, + f.tempo ?? null, + f.rima ?? null, + f.metrica ?? null, + f.compas ?? null, + f.rasgos?.length ? f.rasgos : null + ] + ); + idGenero.set(datos.slug, id); + + if (f.estructura) { + await c.query( + `INSERT INTO genero_seccion (id, genero_id, clave, titulo, cuerpo, orden) + VALUES ($1,$2,'estructura','Estructura de las canciones',$3,0)`, + [nuevoId(), id, f.estructura] + ); + } + for (const [i, tema] of (f.temas ?? []).entries()) { + await c.query( + `INSERT INTO genero_tema (genero_id, etiqueta_id, orden) VALUES ($1,$2,$3) + ON CONFLICT DO NOTHING`, + [id, await etiqueta(tema), i] + ); + } + } + informe.genero = idGenero.size; + void personas; + + for (const { datos, cuerpo } of capitulos) { + await c.query( + `INSERT INTO capitulo (id, slug, titulo, tipo, genero_id, orden, resumen, cuerpo, estado) + VALUES ($1,$2,$3,$4,$5,$6,$7,$8,'publicado')`, + [ + nuevoId(), + datos.slug, + datos.titulo, + datos.tipo, + idGenero.get(datos.slug) ?? null, + datos.orden, + datos.resumen, + cuerpo + ] + ); + } + informe.capitulo = capitulos.length; + + /* --- Blog --------------------------------------------------------------- */ + for (const { datos, cuerpo } of entradas) { + const id = nuevoId(); + await c.query( + `INSERT INTO entrada (id, slug, titulo, fecha, resumen, cuerpo, estado) + VALUES ($1,$2,$3,$4,$5,$6,$7)`, + [ + id, + datos.slug, + datos.titulo, + datos.fecha, + datos.resumen, + cuerpo, + datos.borrador ? 'borrador' : 'publicado' + ] + ); + for (const nombre of datos.etiquetas ?? []) { + await c.query( + `INSERT INTO entrada_etiqueta (entrada_id, etiqueta_id) VALUES ($1,$2) + ON CONFLICT DO NOTHING`, + [id, await etiqueta(nombre)] + ); + } + for (const slug of datos.canciones ?? []) { + const { rows } = await c.query('SELECT id FROM cancion WHERE slug = $1', [slug]); + if (rows[0]) { + await c.query( + `INSERT INTO entrada_cancion (entrada_id, cancion_id) VALUES ($1,$2) + ON CONFLICT DO NOTHING`, + [id, rows[0].id] + ); + } else { + informe.avisos.push(`la entrada «${datos.slug}» cita un tema que no existe: ${slug}`); + } + } + } + informe.entrada = entradas.length; + + /* --- Legales, con su primera versión ------------------------------------ */ + for (const { datos, cuerpo } of legales) { + const id = nuevoId(); + await c.query( + `INSERT INTO documento_legal (id, slug, titulo, resumen, orden) VALUES ($1,$2,$3,$4,$5)`, + [id, datos.slug, datos.titulo, datos.resumen, datos.orden] + ); + const version = nuevoId(); + await c.query( + `INSERT INTO version_legal (id, documento_id, cuerpo, vigente_desde, resumen_cambios) + VALUES ($1,$2,$3,$4,$5)`, + [version, id, cuerpo, new Date(datos.actualizada), 'Primera versión, volcada del repositorio'] + ); + await c.query('UPDATE documento_legal SET version_vigente_id = $1 WHERE id = $2', [ + version, + id + ]); + } + informe.legal = legales.length; + + /* --- Páginas sueltas ------------------------------------------------------ */ + for (const { datos, cuerpo } of paginas) { + await c.query( + `INSERT INTO pagina (id, slug, titulo, descripcion, cuerpo, estado) + VALUES ($1,$2,$3,$4,$5,'publicado')`, + [nuevoId(), datos.slug, datos.titulo, datos.descripcion, cuerpo] + ); + } + informe.pagina = paginas.length; + + /* + * Personas y etiquetas se cuentan AL FINAL y desde la base. Apuntar + * `etiquetas.size` justo después de las canciones daba 18 cuando acaban + * siendo 53: después se crean más con los temas de los géneros y con las del + * blog. Un informe con un número que no es el de la tabla es peor que sin + * número, porque parece comprobado. + */ + for (const tabla of ['persona', 'etiqueta']) { + const { rows } = await c.query(`SELECT count(*)::int n FROM "${tabla}"`); + informe[tabla] = rows[0].n; + } +} + +/* ------------------------------------------------------------------------- + * Comprobar + * ---------------------------------------------------------------------- */ + +/** + * Comprueba que lo escrito coincide con lo leído. + * + * «No dio error» no es lo mismo que «está bien»: un `INSERT` puede meter un + * nulo donde había un texto sin quejarse. + */ +async function comprobar(c, contenido, informe) { + const fallos = []; + + const cuenta = async (tabla, esperado, condicion = '') => { + const { rows } = await c.query(`SELECT count(*)::int n FROM "${tabla}" ${condicion}`); + if (rows[0].n !== esperado) { + fallos.push(`${tabla}: hay ${rows[0].n} y se esperaban ${esperado}`); + } + return rows[0].n; + }; + + await cuenta('estilo', contenido.estilos.length); + await cuenta('album', contenido.albumes.length); + await cuenta('cancion', contenido.canciones.length, 'WHERE version_de_id IS NULL'); + await cuenta('cancion_principal', contenido.canciones.length); + await cuenta('capitulo', contenido.capitulos.length); + await cuenta('entrada', contenido.entradas.length); + await cuenta('documento_legal', contenido.legales.length); + await cuenta('pagina', contenido.paginas.length); + + /* La letra de cada tema, carácter a carácter. */ + for (const { datos, cuerpo } of contenido.canciones) { + const { rows } = await c.query( + 'SELECT titulo, letra, duracion_s, ano FROM cancion WHERE slug = $1', + [datos.slug] + ); + const fila = rows[0]; + if (!fila) { + fallos.push(`falta la canción ${datos.slug}`); + continue; + } + if (fila.titulo !== datos.titulo) fallos.push(`${datos.slug}: el título no coincide`); + if ((fila.letra ?? '') !== (cuerpo || '')) { + fallos.push(`${datos.slug}: la letra no coincide`); + } + if ((fila.duracion_s ?? null) !== (datos.duracion ?? null)) { + fallos.push(`${datos.slug}: la duración no coincide`); + } + if ((fila.ano ?? null) !== (datos.ano ?? null)) { + fallos.push(`${datos.slug}: el año no coincide`); + } + } + + /* Que el extracto siga saliendo igual de la letra guardada. */ + const conLetra = contenido.canciones.find((c) => c.cuerpo); + if (conLetra) { + const { rows } = await c.query('SELECT letra FROM cancion WHERE slug = $1', [conLetra.slug]); + const deLaBase = extraerLineas(rows[0].letra ?? ''); + const delArchivo = extraerLineas(conLetra.cuerpo); + if (deLaBase.join('|') !== delArchivo.join('|')) { + fallos.push('el extracto de la letra no sale igual desde la base'); + } + } + + informe.fallos = fallos; + return fallos.length === 0; +} + +/* ------------------------------------------------------------------------- + * Adelante + * ---------------------------------------------------------------------- */ + +const contenido = { + estilos: leerCarpeta('estilos', parsearEstilo), + albumes: leerCarpeta('albumes', parsearAlbum), + canciones: leerCarpeta('canciones', parsearCancion), + capitulos: leerCarpeta('taller', parsearCapitulo), + entradas: leerCarpeta('blog', parsearEntrada), + legales: leerCarpeta('legal', parsearLegal), + paginas: leerCarpeta('paginas', parsearPagina) +}; + +const total = Object.values(contenido).reduce((n, l) => n + l.length, 0); +console.log(`Leídos ${total} archivos de ${RAIZ}\n`); + +if (SECO) { + for (const [nombre, lista] of Object.entries(contenido)) { + console.log(` ${nombre.padEnd(12)} ${lista.length}`); + } + console.log('\n(en seco: no se ha tocado la base)'); + process.exit(0); +} + +const cliente = new pg.Client({ + connectionString: process.env.DATABASE_URL, + query_timeout: 60_000 +}); +await cliente.connect(); +await cliente.query('BEGIN'); + +const informe = { avisos: [], fallos: [] }; +let bien = false; + +try { + await volcar(cliente, contenido, informe); + bien = await comprobar(cliente, contenido, informe); + await cliente.query(bien ? 'COMMIT' : 'ROLLBACK'); +} catch (fallo) { + await cliente.query('ROLLBACK').catch(() => {}); + console.error('\nFalló el volcado, no se ha escrito nada:\n'); + console.error(' ' + fallo.message); + await cliente.end(); + process.exit(1); +} + +await cliente.end(); + +for (const [tabla, n] of Object.entries(informe)) { + if (typeof n === 'number') console.log(` ${tabla.padEnd(12)} ${n}`); +} +for (const aviso of informe.avisos) console.log(` aviso: ${aviso}`); + +if (bien) { + console.log('\nVolcado y comprobado.'); +} else { + console.log('\nNo cuadra, así que se ha deshecho:'); + for (const f of informe.fallos) console.log(` ✗ ${f}`); + process.exit(1); +} + +void createHash; diff --git a/src/lib/content/fields.ts b/src/lib/content/fields.ts index 1a03b2d..c766e93 100644 --- a/src/lib/content/fields.ts +++ b/src/lib/content/fields.ts @@ -13,13 +13,22 @@ import { esFechaISO } from '$lib/utils/date'; import { duracionASegundos } from '$lib/utils/format'; export class ErrorDeContenido extends Error { - constructor( - readonly archivo: string, - readonly campo: string, - mensaje: string - ) { + readonly archivo: string; + readonly campo: string; + + /* + * Los campos se declaran y se asignan a mano en vez de usar propiedades de + * parametro —`constructor(readonly archivo: string)`—. Aquello es sintaxis + * exclusiva de TypeScript: no se puede borrar el tipo y quedarse con + * JavaScript valido, asi que ningun cargador que solo quite tipos puede con + * ella. Este modulo lo usa tambien el volcado a la base, que corre en Node a + * secas, y por tres lineas de mas no vale la pena cerrarle la puerta. + */ + constructor(archivo: string, campo: string, mensaje: string) { super(`Contenido invalido en ${archivo} -> "${campo}": ${mensaje}`); this.name = 'ErrorDeContenido'; + this.archivo = archivo; + this.campo = campo; } } diff --git a/src/lib/server/db/schema/catalogo.ts b/src/lib/server/db/schema/catalogo.ts index 57902c8..979aa0d 100644 --- a/src/lib/server/db/schema/catalogo.ts +++ b/src/lib/server/db/schema/catalogo.ts @@ -1,10 +1,11 @@ /** * El catálogo: estilos, discos, canciones y todo lo que cuelga de una canción. * - * Hasta ahora esto vivía en `src/content/**` como Markdown con frontmatter. No - * eran documentos: una canción tenía veinte campos estructurados en YAML y la - * letra entera también, y el cuerpo del Markdown eran cuatro líneas de - * comentario. Eran registros disfrazados de documento. + * Hasta ahora esto vivía en `src/content/**` como Markdown con frontmatter, y + * una canción llevaba veintiún campos estructurados en YAML: `registro`, + * `duracion`, `interpretes`, `versiones`, `videos`, `etiquetas`… El cuerpo del + * Markdown sí era contenido de verdad —los versos—, pero todo lo demás eran + * datos con forma de tabla metidos en un archivo de texto. */ import { sql } from 'drizzle-orm'; @@ -149,12 +150,18 @@ export const cancion = pgTable( duracionS: integer('duracion_s'), ano: integer('ano'), - /** Con sus saltos de línea: es verso, no prosa. */ + /** + * Los versos, con sus saltos de línea: es verso, no prosa, y una letra que + * pierde el corte deja de ser la letra. + * + * Es el CUERPO del Markdown de hoy, no un campo del frontmatter. El campo + * `letra:` que aparece en un archivo es otra cosa: quién firma la letra, y + * eso va a `cancion_persona`. + */ letra: text('letra'), /** ISO 639. Decide si la ficha enseña una columna o dos. */ idioma: text('idioma').notNull().default('es'), - /** El cuerpo del Markdown de antes. */ - nota: text('nota'), + /** De dónde sale el tema. Del frontmatter, en párrafos. */ inspiracion: text('inspiracion'), instrumental: boolean('instrumental').notNull().default(false),