Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/malnati/node-gen

NodeJS code generator from database.
https://github.com/malnati/node-gen

Last synced: 4 days ago
JSON representation

NodeJS code generator from database.

Awesome Lists containing this project

README

        

# Node.js Project Generator

Este repositório contém um conjunto de geradores TypeScript para criar a estrutura de um projeto NestJS completo, incluindo módulos, controladores, serviços, entidades TypeORM, DTOs e arquivos de configuração.

## Instalação

O *node-gen* é um pacote Node.js que pode ser instalado globalmente via npm. O registro estaá disponível em [@codegenerator/node-gen](https://www.npmjs.com/package/@codegenerator/node-gen), então você pode instalar o pacote diretamente a partir do NPM.

Para instalar todas as dependências necessárias, execute o comando:

```bash
npm install -g @codegenerator/node-gen
```

## Uso

Este repositório contém vários geradores para criar diferentes partes de um projeto NestJS. Aqui está uma breve descrição de cada gerador:

```bash
npm run build && \
npx ts-node src/main.ts \
--app "Log" \
--host "34.134.67.65" \
--port "5432" \
--database "biud_log" \
--user "biud_log" \
--password "********************" \
--outputDir "./build" \
--components "entities, services, interfaces, controllers, dtos, modules, app-module, main, env, package.json, readme, datasource, diagram" \
--dbType "postgres"
```

## Executando o Gerador

Para executar o gerador e criar toda a estrutura do projeto, use o comando `node-gen`:

```bash
node-gen\
--app "Log" \
--host "34.134.67.65" \
--port "5432" \
--database "biud_log" \
--user "biud_log" \
--password "********************" \
--outputDir "./build" \
--components "entities, services, interfaces, controllers, dtos, modules, app-module, main, env, package.json, readme, datasource, diagram"
```

Este comando executará todos os geradores na ordem correta e copiará os arquivos estáticos para o diretório de destino.

## Estrutura do Projeto Gerado

Após a execução do script, a estrutura do projeto gerado será semelhante a esta:

```bash
./build
├── LICENSE
├── README.md
├── app.module.ts
├── controller
│ ├── example.controller.ts
├── dto
│ ├── create-example.dto.ts
│ ├── update-example.dto.ts
├── entity
│ ├── example.entity.ts
├── interface
│ ├── example.interface.ts
├── main.ts
├── module
│ ├── example.module.ts
├── service
│ ├── example.service.ts
├── static
│ ├── add-header.js
│ ├── bitbucket-pipelines.yml
│ ├── config
│ │ ├── app.readiness.service.ts
│ │ ├── datasource.service.ts
│ │ ├── environment.module.ts
│ │ ├── environment.service.ts
│ │ └── httpsource.service.ts
│ ├── docker-compose.yaml
│ ├── docker-start.sh
│ ├── health
│ │ ├── health.controller.ts
│ │ ├── health.database.indicator.ts
│ │ ├── health.module.ts
│ │ └── health.service.ts
│ ├── jest.config.ts
│ ├── middleware
│ │ ├── jwt-auth.guard.module.ts
│ │ └── jwt-auth.guard.ts
│ ├── tsconfig.build.json
│ ├── tsconfig.json
│ ├── validators
│ │ └── constraint.isRecentDate.ts
│ └── version
│ ├── version.controller.ts
│ └── version.module.ts
```

## Executando o Projeto Gerado

Para executar o projeto gerado, use os seguintes comandos:

1. Navegue até o diretório `./build`:
```bash
cd build
```

2. Instale as dependências do projeto gerado:
```bash
npm install
```

3. Inicie o projeto:
```bash
npm start
```

Isso iniciará o servidor NestJS usando as configurações geradas.

---

### Licença

Este projeto é licenciado sob a licença MIT - veja o arquivo [LICENSE](LICENSE) para mais detalhes.

## Pre-requisitos

Crie seu modelo relacional no PostgreSQL e em seguida execute o script abaixo para criar as funções e triggers necessários para garantir a integridade dos dados.

```SQL
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
SELECT uuid_generate_v4();

CREATE FUNCTION public.prevent_created_at_update() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF OLD IS NOT NULL AND NEW.created_at <> OLD.created_at THEN
RAISE EXCEPTION 'Não é possível atualizar o campo created_at após a criação do registro.';
END IF;
RETURN NEW;
END;
$$;

CREATE FUNCTION public.prevent_deleted_at_update() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF OLD IS NOT NULL AND OLD.created_at IS NOT null THEN
RAISE EXCEPTION 'Não é possível atualizar o campo deleted_at.';
END IF;
RETURN NEW;
END;
$$;

CREATE FUNCTION public.prevent_delete() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION 'Não é possível excluir o registro. Operação não permitida.';
RETURN NEW;
END;
$$;

CREATE FUNCTION public.prevent_update() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION 'Não é possível atualizar o registro. Operação não permitida.';
RETURN NEW;
END;
$$;

DO $$
DECLARE
tbl RECORD;
col_exists BOOLEAN;
trg_update_name TEXT;
trg_delete_name TEXT;
trg_update_deleted_at_name TEXT;
index_name TEXT;
BEGIN
-- Lista todas as tabelas no esquema public com prefixo 'tb_'
FOR tbl IN
SELECT tablename
FROM pg_tables
WHERE schemaname = 'public' AND tablename LIKE 'tb_%'
LOOP
-- Verifica se a coluna 'created_at' já existe na tabela
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = tbl.tablename
AND column_name = 'created_at'
) INTO col_exists;

-- Se a coluna não existir, adiciona a coluna 'created_at'
IF NOT col_exists THEN
EXECUTE format('ALTER TABLE %I ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP', tbl.tablename);
END IF;

-- Adiciona ou atualiza o comentário na coluna 'created_at'
EXECUTE format('COMMENT ON COLUMN %I.created_at IS ''Data de criação do registro.''', tbl.tablename);

-- Verifica se a coluna 'updated_at' já existe na tabela
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = tbl.tablename
AND column_name = 'updated_at'
) INTO col_exists;

-- Se a coluna não existir, adiciona a coluna 'updated_at'
IF NOT col_exists THEN
EXECUTE format('ALTER TABLE %I ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP', tbl.tablename);
END IF;

-- Adiciona ou atualiza o comentário na coluna 'updated_at'
EXECUTE format('COMMENT ON COLUMN %I.updated_at IS ''Data de atualização do registro.''', tbl.tablename);

-- Verifica se a coluna 'deleted_at' já existe na tabela
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = tbl.tablename
AND column_name = 'deleted_at'
) INTO col_exists;

-- Se a coluna não existir, adiciona a coluna 'deleted_at'
IF NOT col_exists THEN
EXECUTE format('ALTER TABLE %I ADD COLUMN deleted_at TIMESTAMP', tbl.tablename);
END IF;

-- Adiciona ou atualiza o comentário na coluna 'deleted_at'
EXECUTE format('COMMENT ON COLUMN %I.deleted_at IS ''Data da exclusão lógica do registro.''', tbl.tablename);

-- Verifica se a coluna 'external_id' já existe na tabela
SELECT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = tbl.tablename
AND column_name = 'external_id'
) INTO col_exists;

-- Se a coluna não existir, adiciona a coluna 'external_id'
IF NOT col_exists THEN
EXECUTE format('ALTER TABLE %I ADD COLUMN external_id UUID DEFAULT uuid_generate_v4() NOT NULL', tbl.tablename);
END IF;

-- Adiciona ou atualiza o comentário na coluna 'external_id'
EXECUTE format('COMMENT ON COLUMN %I.external_id IS ''Identificador único externo de registros desta tabela. Este campo é obrigatório.''', tbl.tablename);

-- Nome do índice único na coluna 'external_id'
index_name := tbl.tablename || '_external_id_idx';

-- Cria o índice único na coluna 'external_id' se não existir
IF NOT EXISTS (
SELECT 1
FROM pg_indexes
WHERE tablename = tbl.tablename
AND indexname = index_name
) THEN
EXECUTE format('CREATE UNIQUE INDEX %I ON %I (external_id)', index_name, tbl.tablename);
END IF;

-- Nome das triggers baseado no nome da tabela
trg_update_name := tbl.tablename || '_fire_update_rules';
trg_delete_name := tbl.tablename || '_fire_delete_rules';
trg_update_deleted_at_name := tbl.tablename || '_fire_update_deleted_at_rules';

-- Verifica se a trigger de update já existe e a remove se necessário
IF EXISTS (
SELECT 1
FROM pg_trigger
WHERE tgname = trg_update_name
AND tgrelid = tbl.tablename::regclass
) THEN
EXECUTE format('DROP TRIGGER %I ON %I', trg_update_name, tbl.tablename);
END IF;

-- Cria a trigger de update
EXECUTE format('
CREATE TRIGGER %I
BEFORE UPDATE ON %I
FOR EACH ROW
EXECUTE FUNCTION public.prevent_created_at_update();
', trg_update_name, tbl.tablename);

-- Verifica se a trigger de delete já existe e a remove se necessário
IF EXISTS (
SELECT 1
FROM pg_trigger
WHERE tgname = trg_delete_name
AND tgrelid = tbl.tablename::regclass
) THEN
EXECUTE format('DROP TRIGGER %I ON %I', trg_delete_name, tbl.tablename);
END IF;

-- Cria a trigger de delete
EXECUTE format('
CREATE TRIGGER %I
BEFORE DELETE ON %I
FOR EACH ROW
EXECUTE FUNCTION public.prevent_delete();
', trg_delete_name, tbl.tablename);

-- Verifica se a trigger de update em 'deleted_at' já existe e a remove se necessário
IF EXISTS (
SELECT 1
FROM pg_trigger
WHERE tgname = trg_update_deleted_at_name
AND tgrelid = tbl.tablename::regclass
) THEN
EXECUTE format('DROP TRIGGER %I ON %I', trg_update_deleted_at_name, tbl.tablename);
END IF;

-- Cria a trigger de update em 'deleted_at'
EXECUTE format('
CREATE TRIGGER %I
BEFORE UPDATE ON %I
FOR EACH ROW
EXECUTE FUNCTION public.prevent_deleted_at_update();
', trg_update_deleted_at_name, tbl.tablename);

END LOOP;
END $$;
```