feat(api): módulo de consultas de solo lectura a la base de SAP (HANA con hdb): consultas registradas con parámetros con nombre, cola, auditoría y extensión por cliente
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9118985d96
commit
3e27f370dc
21 files changed
+770
-2
No files matched your search
@@ -0,0 +1,36 @@
|
||||
import { assertReadOnly, paramNames } from './sapdb-sql.js';
|
||||
import { CLIENT_SAPDB_QUERIES } from './sapdb.extensions.js';
|
||||
import type { SapDbQuery } from './sapdb.types.js';
|
||||
|
||||
/** Consultas del proyecto base: solo una de comprobación (la base responde). Las de negocio van en `sapdb.extensions.ts`. */
|
||||
export const BASE_SAPDB_QUERIES: readonly SapDbQuery[] = [
|
||||
{
|
||||
name: 'ping',
|
||||
title: 'Comprobar la conexión con la base de datos',
|
||||
sql: { hana: 'SELECT 1 AS "ok" FROM "DUMMY"' },
|
||||
params: {},
|
||||
menu: null,
|
||||
},
|
||||
];
|
||||
|
||||
/** Comprueba que los nombres no se repitan, que el SQL sea de solo lectura y que use justo los parámetros declarados. Lanza si no. */
|
||||
export function validateQueries(queries: readonly SapDbQuery[]): readonly SapDbQuery[] {
|
||||
const seen = new Set<string>();
|
||||
for (const q of queries) {
|
||||
if (!/^[a-z0-9][a-z0-9-]{0,59}$/.test(q.name)) throw new Error(`Nombre de consulta inválido: ${q.name}`);
|
||||
if (seen.has(q.name)) throw new Error(`Consulta repetida: ${q.name}`);
|
||||
seen.add(q.name);
|
||||
const engines = Object.entries(q.sql);
|
||||
if (!engines.length) throw new Error(`La consulta ${q.name} no tiene SQL`);
|
||||
for (const [engine, sql] of engines) {
|
||||
assertReadOnly(`${q.name} (${engine})`, sql);
|
||||
const used = new Set(paramNames(sql));
|
||||
const declared = new Set(Object.keys(q.params));
|
||||
for (const n of used) if (!declared.has(n)) throw new Error(`La consulta ${q.name} (${engine}) usa :${n} sin declararlo`);
|
||||
for (const n of declared) if (!used.has(n)) throw new Error(`La consulta ${q.name} (${engine}) declara ${n} y no lo usa`);
|
||||
}
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
export const SAPDB_QUERIES: ReadonlyMap<string, SapDbQuery> = new Map(validateQueries([...BASE_SAPDB_QUERIES, ...CLIENT_SAPDB_QUERIES]).map((q) => [q.name, q]));
|
||||
Reference in new issue
Block a user