You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.9 KiB
103 lines
2.9 KiB
/**
|
|
* Carga el glosario del taller.
|
|
*
|
|
* npm run db:glosario
|
|
*
|
|
* Veintiocho términos con sus acepciones numeradas y las formas con las que
|
|
* aparecen de verdad en el texto. Es lo que hace posible el marcado: sin las
|
|
* variantes, «sinalefas» en plural no se reconocería y nadie echaría en falta
|
|
* el globo que no salió.
|
|
*
|
|
* Idempotente por slug: reimportar una definición corregida actualiza. Las
|
|
* acepciones se rehacen enteras —se borran y se vuelven a poner— porque su
|
|
* número es su identidad y renumerar a mano dejaría huecos.
|
|
*/
|
|
|
|
import fs from 'node:fs';
|
|
import pg from 'pg';
|
|
|
|
const SEMILLA = JSON.parse(fs.readFileSync('scripts/db/semilla-glosario.json', 'utf8'));
|
|
|
|
const slugificar = (t) =>
|
|
t
|
|
.toLowerCase()
|
|
.normalize('NFD')
|
|
.replace(/[̀-ͯ]/g, '')
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
const c = new pg.Client({ connectionString: process.env.DATABASE_URL, query_timeout: 60_000 });
|
|
await c.connect();
|
|
await c.query('BEGIN');
|
|
|
|
const contado = { termino: 0, acepcion: 0, variante: 0 };
|
|
const avisos = [];
|
|
|
|
try {
|
|
const vistos = new Set();
|
|
|
|
for (const t of SEMILLA.terminos) {
|
|
const slug = slugificar(t.termino);
|
|
if (vistos.has(slug)) {
|
|
avisos.push(`«${t.termino}» sale dos veces en la semilla`);
|
|
continue;
|
|
}
|
|
vistos.add(slug);
|
|
|
|
const { rows } = await c.query(
|
|
`INSERT INTO termino (id, slug, termino) VALUES ($1,$2,$3)
|
|
ON CONFLICT (slug) DO UPDATE SET termino = EXCLUDED.termino
|
|
RETURNING id`,
|
|
[crypto.randomUUID(), slug, t.termino]
|
|
);
|
|
const terminoId = rows[0].id;
|
|
contado.termino++;
|
|
|
|
await c.query('DELETE FROM acepcion WHERE termino_id = $1', [terminoId]);
|
|
for (const [i, a] of t.acepciones.entries()) {
|
|
await c.query(
|
|
`INSERT INTO acepcion (id, termino_id, numero, categoria, definicion, ampliacion, ejemplo)
|
|
VALUES ($1,$2,$3,$4,$5,$6,$7)`,
|
|
[
|
|
crypto.randomUUID(),
|
|
terminoId,
|
|
i + 1,
|
|
a.categoria,
|
|
a.definicion,
|
|
a.ampliacion ?? null,
|
|
a.ejemplo ?? null
|
|
]
|
|
);
|
|
contado.acepcion++;
|
|
}
|
|
|
|
/*
|
|
* El propio término también es una forma buscable, así no hay que
|
|
* repetirlo en la lista de variantes de los veintiocho.
|
|
*/
|
|
await c.query('DELETE FROM termino_variante WHERE termino_id = $1', [terminoId]);
|
|
for (const forma of new Set([t.termino, ...(t.variantes ?? [])])) {
|
|
await c.query(
|
|
'INSERT INTO termino_variante (termino_id, forma) VALUES ($1,$2) ON CONFLICT DO NOTHING',
|
|
[terminoId, forma.toLowerCase()]
|
|
);
|
|
contado.variante++;
|
|
}
|
|
}
|
|
|
|
await c.query('COMMIT');
|
|
} catch (fallo) {
|
|
await c.query('ROLLBACK').catch(() => {});
|
|
console.error('Falló, no se ha escrito nada:');
|
|
console.error(' ' + fallo.message);
|
|
await c.end();
|
|
process.exit(1);
|
|
}
|
|
|
|
await c.end();
|
|
|
|
for (const [que, n] of Object.entries(contado)) console.log(` ${que.padEnd(10)} ${n}`);
|
|
for (const aviso of avisos) console.log(` aviso: ${aviso}`);
|
|
console.log('');
|
|
console.log('Glosario cargado.');
|