mp-holistic
Version:
si prefigge l'umile compito di aiutare nella creazione di : - un server API REST mediante express - un semplice ORM per Postgres Questo tramite decoratori o classi particolari.
353 lines (321 loc) • 14.9 kB
text/typescript
import { IMetaClasse, ListaMetadataClasse, MetadataClasse } from "../metadata/classe.metadata";
import { IGrant, typeGrantEvent } from "./grant";
import { ListaPolicy } from "./policy";
import { ListaPostgresProprieta, PostgresProprieta } from "./proprieta.postgres";
export interface IPostgresClasse extends IMetaClasse {
queryPerVista?: string,
nomeTabella?: string,
like?: string,
estende?: string,
abilitaCreatedAt?: boolean,
abilitaUpdatedAt?: boolean,
abilitaDeletedAt?: boolean,
creaId?: boolean,
listaPolicy?: ListaPolicy,
grants?: IGrant[],
multiUnique?: { colonneDiRiferimento: string[] }[]
}
export class PostgresClasse extends MetadataClasse implements IPostgresClasse {
queryPerVista?: string;
listaProprieta: ListaPostgresProprieta = new ListaPostgresProprieta();
nomeTabella: string;
like?: string;
estende?: string;
abilitaCreatedAt: boolean;
abilitaUpdatedAt: boolean;
abilitaDeletedAt: boolean;
creaId: boolean;
listaPolicy?: ListaPolicy;
grants?: IGrant[]
multiUnique?: { colonneDiRiferimento: string[] }[] = [];
faxSimile_abilitaDeletedAt = `created_at timestamp with time zone NOT NULL DEFAULT current_timestamp`;
faxSimile_abilitaCreatedAt = `updated_at timestamp with time zone NOT NULL DEFAULT current_timestamp`;
faxSimile_abilitaUpdatedAt = `deleted_at timestamp with time zone`;
faxsSimileIntestazione = 'CREATE TABLE IF NOT EXISTS ';
faxsSimileIntestazioneView = 'CREATE OR REPLACE VIEW ';
constructor(item: IPostgresClasse) {
super(item);
if ((this.nomeOriginale == '' || this.nomeOriginale == undefined) &&
item.nomeTabella)
this.nomeOriginale = item.nomeTabella;
this.creaId = item.creaId ?? true;
this.nomeTabella = item.nomeTabella ?? this.nomeOriginale;
//this.listaProprieta = new Lista();
this.abilitaCreatedAt = item.abilitaCreatedAt ?? true;
this.abilitaDeletedAt = item.abilitaDeletedAt ?? true;
this.abilitaUpdatedAt = item.abilitaUpdatedAt ?? true;
if (item.grants) {
this.grants = item.grants;
}
}
CostruisciCreazioneDB(/* client: Client */elencoQuery: string[], padreEreditario: boolean) {
let rigaDaInserire = '';
let ritornoTmp = '';
if (this.estende == undefined && this.like == undefined && padreEreditario == true) rigaDaInserire = '); \n';
else if (this.estende && padreEreditario == false) rigaDaInserire = ') INHERITS("' + this.estende + '");' + '\n';
else if (this.like && padreEreditario == false) rigaDaInserire = 'LIKE "' + this.like + '"' + '\n';
else { rigaDaInserire = '); \n'; }
if (rigaDaInserire != undefined) {
let checkTmp = false;
if (this.queryPerVista == undefined || this.queryPerVista == '') {
ritornoTmp = ritornoTmp + this.faxsSimileIntestazione + '"' + this.nomeTabella + '"' + ' (' + '\n';
if (this.abilitaCreatedAt) { ritornoTmp = ritornoTmp + this.faxSimile_abilitaCreatedAt + ',' + '\n'; }
if (this.abilitaDeletedAt) { ritornoTmp = ritornoTmp + this.faxSimile_abilitaDeletedAt + ',' + '\n'; }
if (this.abilitaUpdatedAt) { ritornoTmp = ritornoTmp + this.faxSimile_abilitaUpdatedAt; }
if (this.listaProprieta.length) ritornoTmp = ritornoTmp + ',' + '\n';
else ritornoTmp = ritornoTmp + '\n';
for (let index = 0; index < this.listaProprieta.length; index++) {
const element = <PostgresProprieta>this.listaProprieta[index];
ritornoTmp = ritornoTmp + element.CostruisciCreazioneDB(this.nomeTabella);
if (index + 1 < this.listaProprieta.length) ritornoTmp = ritornoTmp + ',' + '\n';
else {
if (this.creaId) {
ritornoTmp = ritornoTmp + ',\n';
ritornoTmp = ritornoTmp + CreaID() + '\n';
checkTmp = true;
} else {
ritornoTmp = ritornoTmp + '\n';
}
}
}
if (this.creaId == true && checkTmp == false) {
if (this.listaProprieta.length > 0) {
ritornoTmp = ritornoTmp + ',\n';
ritornoTmp = ritornoTmp + CreaID() + '\n';
}
else if (this.abilitaUpdatedAt || this.abilitaCreatedAt || this.abilitaDeletedAt) {
ritornoTmp = ritornoTmp + ',\n' + CreaID() + '\n';
}
else {
ritornoTmp = ritornoTmp + CreaID() + '\n';
}
}
if (this.multiUnique) {
for (let index = 0; index < this.multiUnique.length; index++) {
const element = this.multiUnique[index];
let ritornoTmp2 = 'UNIQUE (';
for (let ind = 0; ind < element.colonneDiRiferimento.length; ind++) {
const variab = element.colonneDiRiferimento[ind];
ritornoTmp2 = ritornoTmp2 + ' ' + variab;
if (ind + 1 < element.colonneDiRiferimento.length) ritornoTmp2 = ritornoTmp2 + ',';
}
ritornoTmp2 = ritornoTmp2 + ' )';
if (ritornoTmp2 != 'UNIQUE ( )') {
ritornoTmp = ritornoTmp + ritornoTmp2;
}
}
}
ritornoTmp = ritornoTmp + rigaDaInserire;
}
else {
ritornoTmp = ritornoTmp + this.faxsSimileIntestazioneView + '"' + this.nomeTabella + '"' + ' (';
for (let index = this.listaProprieta.length - 1; index >= 0; index--) {
const element = <PostgresProprieta>this.listaProprieta[index];
ritornoTmp = ritornoTmp + " " + element.nome + " ";
if (index - 1 >= 0) ritornoTmp = ritornoTmp + '\n ';
}
ritornoTmp = ritornoTmp + " )\n AS " + this.queryPerVista + '\n';
}
elencoQuery.push(ritornoTmp); //CREAZIONE TABELLA :CREATE NEW TABLE ECC..
/* */
//elencoQuery.push(`ALTER TABLE ${this.nomeTabella} ENABLE ROW LEVEL SECURITY;`);
ritornoTmp = '';
/* Ora che la tabella esiste vado ad eseguire i trigger */
for (let index = 0; index < this.listaProprieta.length; index++) {
const element = <PostgresProprieta>this.listaProprieta[index];
element.CostruisceTrigger(this.nomeTabella, elencoQuery);
}
if (this.abilitaDeletedAt && this.abilitaUpdatedAt && this.queryPerVista == undefined) {
elencoQuery.push(TriggerUpdate(this.nomeTabella));
}
if (this.abilitaDeletedAt && this.abilitaUpdatedAt && this.queryPerVista == undefined) {
elencoQuery.push(TriggerDeleted_at(this.nomeTabella));
}
}
return ritornoTmp;
}
CostruisciRelazioniDB(/* client: Client */elencoQuery: string[]) {
let ritorno = '';
/* if (this.estende) {
const query = `ALTER TABLE ${this.nomeTabella} INHERIT ${this.estende};`
EseguiQueryControllata(client, query);
} */
for (let index = 0; index < this.listaProprieta.length; index++) {
const element = <PostgresProprieta>this.listaProprieta[index];
const tmp = element.CostruisciRelazioniDB(this.nomeTabella);
ritorno = ritorno + '\n' + tmp;
elencoQuery.push(tmp);
}
return ritorno;
}
CostruisceGrant(grants: IGrant[],/* client: Client */ elencoQuery: string[]) {
let ritorno = '';
for (let index = 0; index < grants.length; index++) {
const element = grants[index];
if (element.colonneRiferimento && element.colonneRiferimento.length > 0) {
for (let index = 0; index < element.colonneRiferimento.length; index++) {
const colonna = element.colonneRiferimento[index];
const eventitesto = CostruisciEvents(element.events, colonna);
const ruolitesto = CostruisciRuoli(element.ruoli);
const tmp = `GRANT ${eventitesto}
ON public."${this.nomeTabella}"
TO ${ruolitesto};`;
elencoQuery.push(tmp);
ritorno = ritorno + '\n' + tmp;
}
}
else {
const eventitesto = CostruisciEvents(element.events);
const ruolitesto = CostruisciRuoli(element.ruoli);
const tmp = `GRANT ${eventitesto}
ON public."${this.nomeTabella}"
TO ${ruolitesto};`;
elencoQuery.push(tmp);
ritorno = ritorno + '\n' + tmp;
}
}
for (let index = 0; index < this.listaProprieta.length; index++) {
const element = <PostgresProprieta>this.listaProprieta[index];
for (let index = 0; element.grants && index < element.grants.length; index++) {
const element2 = element.grants[index];
const eventitesto = CostruisciEvents(element2.events, element.nome);
const ruolitesto = CostruisciRuoli(element2.ruoli);
const tmp = `GRANT ${eventitesto}
ON public."${this.nomeTabella}"
TO ${ruolitesto};`;
elencoQuery.push(tmp);
ritorno = ritorno + '\n' + tmp;
}
}
return ritorno;
}
Mergia(item: PostgresClasse) {
super.Mergia(item);
this.creaId = item.creaId;
this.nomeTabella = item.nomeTabella;
//this.listaProprieta = new Lista();
this.abilitaCreatedAt = item.abilitaCreatedAt;
this.abilitaDeletedAt = item.abilitaDeletedAt;
this.abilitaUpdatedAt = item.abilitaUpdatedAt;
if (item.grants) this.grants = item.grants;
}
}
export class ListaPostgresClasse extends ListaMetadataClasse {
constructor(item?: ListaPostgresClasse) {
super();
if (item)
for (let index = 0; index < item.length; index++) {
const element = new PostgresClasse(<PostgresClasse>item[index]);
const tmp = this.Cerca(element);
if (tmp) tmp.Mergia(element);
}
}
Mergia(item: ListaPostgresClasse) {
const t = super.Mergia(item);
return t;
}
CercaSeNoAggiungi(item: PostgresClasse) {
const t = super.CercaSeNoAggiungi(item);
return <PostgresClasse>t;
}
Cerca(item: PostgresClasse) {
const t = super.CercaSeNoAggiungi(item);
return <PostgresClasse>t;
}
AggiungiElemento(item: PostgresClasse) {
const t = super.AggiungiElemento(item);
return <PostgresClasse>t;
}
}
export function TriggerDeleted_at(nomeTabella: string) {
return `CREATE INDEX IF NOT EXISTS idx_somethings_deleted_at ON "${nomeTabella}" (deleted_at ASC);`;
}
export function TriggerUpdate(nomeTabella: string) {
return `DROP TRIGGER IF EXISTS tr_somethings_updated_at ON "${nomeTabella}";
CREATE TRIGGER tr_somethings_updated_at
BEFORE UPDATE
ON "${nomeTabella}"
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();`
}
export function CostruisciFunzione(item: any, nomeFunzioneCheck: string, nomePolicy: string, typeFunctionCheck: string,
carattere: string | 'CK' | 'US', /* client: Client */elencoQuery: string[]): string {
let corpoFunzione = '';
if (item) {
if (typeof item === 'function') {
const strg = String(item);
const tt = strg.indexOf('{');
const t1 = strg.substring(tt + 1, strg.length);
const t2 = t1.lastIndexOf('}');
const t3 = t1.substring(0, t2 - 1);
corpoFunzione = t3;
console.log(strg);
}
else {
corpoFunzione = String(item);
}
const tmp = `
CREATE OR REPLACE FUNCTION "${carattere}_FN_${nomeFunzioneCheck}_xTR_${nomePolicy}"() RETURNS boolean AS
$$
${corpoFunzione}
$$
LANGUAGE "${typeFunctionCheck ?? 'plv8'}";
`;
const ritorno = '' + carattere + '_FN_' + nomeFunzioneCheck + '_xTR_' + nomePolicy + '';
//await EseguiQueryControllata(client, tmp);
elencoQuery.push(tmp);
return ritorno;
}
return '';
}
export function CostruisciRuoli(ruoli: string[]) {
let ritorno = '';
for (let index = 0; index < ruoli.length; index++) {
const element = ruoli[index];
ritorno = ritorno + element;
if (ruoli.length >= 2 && index + 1 < ruoli.length) {
ritorno = ritorno + ', ';
}
}
return ritorno;
}
export function CostruisciEvents(events: typeGrantEvent[], nome?: string) {
let ritorno = ' ';
for (let index = 0; index < events.length; index++) {
const element = events[index];
if (nome) {
ritorno = ritorno + element + '("' + nome + '")';
} else {
ritorno = ritorno + element;
}
if (events.length >= 2 && index + 1 < events.length) {
ritorno = ritorno + ', ';
}
}
return ritorno;
}
export function CreaID() {
return "id SERIAL PRIMARY KEY";
}
export function TriggerUpdate_updated_at_column() {
return `CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$ language 'plpgsql';`;
}
export function CreateDataBase(nomeDB: string) {
return `CREATE DATABASE ${nomeDB};`;
}
export function DropDataBase(nomeDB: string) {
return `DROP DATABASE IF EXISTS "${nomeDB}";`;
}
export function DropAllTable() {
return `DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';`;
}