Skip to content

Commit

Permalink
Geração de Visões por linha de comando (#31)
Browse files Browse the repository at this point in the history
* - Restruturação do comando gerar para algo mais organizado;
- Atualização do pacote `@designliquido/flexoes`.
* Esboço da ideia de geração de visões.
* Apagando exemplos.
  • Loading branch information
leonelsanchesdasilva authored Jan 13, 2024
1 parent 28df8f1 commit 9ae3e16
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 87 deletions.
63 changes: 25 additions & 38 deletions index-gerar.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import * as sistemaArquivos from 'fs';
import * as caminho from 'path';

import prompts from 'prompts';

import { Lexador } from '@designliquido/delegua/fontes/lexador';
import { AvaliadorSintatico } from '@designliquido/delegua/fontes/avaliador-sintatico';
import { Importador } from '@designliquido/delegua-node/fontes/importador';
import { Classe } from '@designliquido/delegua/fontes/declaracoes';
import { pluralizar } from '@designliquido/flexoes';

import { criarDiretorioSeNaoExiste, criarNovaVisao, criarNovoControlador, importarModelos, obterTodosModelos } from './interface-linha-comando/gerar';

const pontoDeEntradaGerar = async (argumentos: string[]) => {
// argumentos[0] normalmente é o nome do executável, seja Node, Bun, etc.
// argumentos[1] é o nome do arquivo deste ponto de entrada.
// argumentos[2] é o nome do modelo correspondente. Se vir vazio, perguntar o nome.
let nomeModelo = argumentos[2];
const diretorioModelos = caminho.join(process.cwd(), 'modelos');

if (nomeModelo === undefined || nomeModelo.length <= 0) {
const opcoesModelos = [];
sistemaArquivos.readdirSync(diretorioModelos).forEach((arquivo) => {
if (arquivo.endsWith('.delegua')) {
const prefixoArquivo = arquivo.split('.')[0];
opcoesModelos.push({ title: prefixoArquivo, value: prefixoArquivo });
}
});
const opcoesModelos = obterTodosModelos();

const respostaNomeModelo = await prompts({
type: 'select',
Expand All @@ -34,34 +24,31 @@ const pontoDeEntradaGerar = async (argumentos: string[]) => {
nomeModelo = respostaNomeModelo.nomeModelo;
}

const lexador = new Lexador(false);
const avaliadorSintatico = new AvaliadorSintatico(false);
const importador = new Importador(lexador, avaliadorSintatico, {}, {}, false);

const resultadoImportacao = importador.importar(caminho.join(diretorioModelos, nomeModelo + '.delegua'));
const declaracoes = resultadoImportacao.retornoAvaliadorSintatico.declaracoes;
const declaracoes = importarModelos(nomeModelo);
criarDiretorioSeNaoExiste('controladores');

// Aqui apenas aceitamos declarações de classes. Pode ser mais de uma.
for (const declaracao of declaracoes.filter((d) => d instanceof Classe)) {
const declaracaoClasse = <Classe>declaracao;

const diretorioControladores = caminho.join(process.cwd(), 'controladores');

if (!sistemaArquivos.existsSync(diretorioControladores)) {
sistemaArquivos.mkdirSync(diretorioControladores);
}

// Controlador: cria-se um arquivo `.delegua` com quatro rotas: rotaGet, rotaPost, rotaPut, rotaDelete.
const nomeControladorPlural = pluralizar(declaracaoClasse.simbolo.lexema).toLocaleLowerCase('pt');

const conteudoControlador = `liquido.rotaGet(funcao(requisicao, resposta) {\n resposta.lmht({ "titulo": "Liquido" })\n})`;
const caminhoControlador = caminho.join(diretorioControladores, nomeControladorPlural + '.delegua');
sistemaArquivos.writeFileSync(
caminhoControlador,
conteudoControlador
);

console.info(`Controlador ${caminhoControlador} criado com sucesso!`);
const nomeBaseModelo = declaracaoClasse.simbolo.lexema.toLocaleLowerCase('pt');
const nomeControladorPlural = pluralizar(nomeBaseModelo).toLocaleLowerCase('pt');

const caminhoControlador = criarNovoControlador(nomeControladorPlural);
console.info(`Controlador ${caminhoControlador}`);

// Visões
criarDiretorioSeNaoExiste('visoes', nomeControladorPlural);

const visaoSelecionarTudo = criarNovaVisao(nomeControladorPlural, 'selecionarTudo');
console.info(`Visão ${visaoSelecionarTudo}`);
const visaoSelecionarUm = criarNovaVisao(nomeControladorPlural, 'selecionarUm');
console.info(`Visão ${visaoSelecionarUm}`);
const visaoAdicionar = criarNovaVisao(nomeControladorPlural, 'adicionar');
console.info(`Visão ${visaoAdicionar}`);
const visaoAtualizar = criarNovaVisao(nomeControladorPlural, 'atualizar');
console.info(`Visão ${visaoAtualizar}`);
const visaoExcluir = criarNovaVisao(nomeControladorPlural, 'excluir');
console.info(`Visão ${visaoExcluir}`);
}
};

Expand Down
2 changes: 1 addition & 1 deletion index-novo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import prompts from 'prompts';
import { copiarExemploParaProjeto, criarDiretorioAplicacao } from './interface-linha-comando';
import { copiarExemploParaProjeto, criarDiretorioAplicacao } from './interface-linha-comando/novo';

const pontoDeEntradaNovo = async (argumentos: string[]) => {
// argumentos[0] normalmente é o nome do executável, seja Node, Bun, etc.
Expand Down
119 changes: 119 additions & 0 deletions interface-linha-comando/gerar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import * as sistemaArquivos from 'fs';
import * as caminho from 'path';

import { Lexador } from '@designliquido/delegua/fontes/lexador';
import { AvaliadorSintatico } from '@designliquido/delegua/fontes/avaliador-sintatico';
import { Importador } from '@designliquido/delegua-node/fontes/importador';
import { Declaracao } from '@designliquido/delegua/fontes/declaracoes';

import { TipoVisao } from './tipo-visao';

/**
* Obtém todos os modelos do diretório 'modelos' do projeto.
* @returns {{ title: string, value: string }[]} Um vetor com todos os arquivos de modelos encontrados.
*/
export function obterTodosModelos(): { title: string, value: string }[] {
const diretorioModelos = caminho.join(process.cwd(), 'modelos');
const opcoesModelos = [];

sistemaArquivos.readdirSync(diretorioModelos).forEach((arquivo) => {
if (arquivo.endsWith('.delegua')) {
const prefixoArquivo = arquivo.split('.')[0];
opcoesModelos.push({ title: prefixoArquivo, value: prefixoArquivo });
}
});

return opcoesModelos;
}

/**
* Dado o nome de um arquivo de modelos, retorna todas as declarações de modelos.
* @param {string} nomeModelo O nome do arquivo no diretório 'modelos' que contém os modelos.
* @returns {Declaracao[]} Um vetor de declarações de classes em Delégua.
*/
export function importarModelos(nomeModelo: string): Declaracao[] {
const diretorioModelos = caminho.join(process.cwd(), 'modelos');
const lexador = new Lexador(false);
const avaliadorSintatico = new AvaliadorSintatico(false);
const importador = new Importador(lexador, avaliadorSintatico, {}, {}, false);

const resultadoImportacao = importador.importar(caminho.join(diretorioModelos, nomeModelo + '.delegua'));
const declaracoes = resultadoImportacao.retornoAvaliadorSintatico.declaracoes;
return declaracoes;
}

/**
* Cria na raiz do projeto um diretório passado por parâmetro, se já não existir.
* @param {string} partesDiretorio O diretório a ser verificado/criado.
*/
export function criarDiretorioSeNaoExiste(...partesDiretorio: string[]) {
const caminhoDiretorio = caminho.join(process.cwd(), ...partesDiretorio);

if (!sistemaArquivos.existsSync(caminhoDiretorio)) {
sistemaArquivos.mkdirSync(caminhoDiretorio);
}
}

/**
* Cria um arquivo `.delegua` no diretório 'controladores' com quatro rotas:
* - rotaGet (para selecionar 1 ou vários registros na base de dados)
* - rotaPost (para gravar 1 registro na base de dados)
* - rotaPut (para alterar 1 registro na base de dados)
* - rotaDelete (para excluir 1 registro na base de dados)
* @param {string} nome O nome do controlador.
* @returns {string} O caminho completo onde o controlador foi criado.
*/
export function criarNovoControlador(nome: string): string {
const diretorioControladores = caminho.join(process.cwd(), 'controladores');

const conteudoControlador = `liquido.rotaGet(funcao(requisicao, resposta) {\n resposta.lmht({ "titulo": "Liquido" })\n})`;
const caminhoControlador = caminho.join(diretorioControladores, nome + '.delegua');
sistemaArquivos.writeFileSync(
caminhoControlador,
conteudoControlador
);

return caminhoControlador;
}

/**
* Cria uma nova visão, de acordo com o nome do controlador e o tipo de visão desejado.
* @param {string} nomeControlador O nome do controlador.
* @param {TipoVisao} tipoVisao O tipo da visão.
* @returns O caminho completo onde a visão foi criada.
*/
export function criarNovaVisao(nomeControlador: string, tipoVisao: TipoVisao) {
let caminhoVisao: string;
let conteudoVisao: string;
const diretorioVisoes = caminho.join(process.cwd(), 'visoes', nomeControlador);

switch (tipoVisao) {
case 'selecionarTudo':
caminhoVisao = caminho.join(diretorioVisoes, 'inicial.lmht');
conteudoVisao = `<lmht>\n <cabeça><título>Teste</título></cabeça>\n<corpo>Teste</corpo>\n</lmht>`;
break;
case 'selecionarUm':
caminhoVisao = caminho.join(diretorioVisoes, 'detalhes.lmht');
conteudoVisao = `<lmht>\n <cabeça><título>Teste</título></cabeça>\n<corpo>Teste</corpo>\n</lmht>`;
break;
case 'adicionar':
caminhoVisao = caminho.join(diretorioVisoes, 'adicionar.lmht');
conteudoVisao = `<lmht>\n <cabeça><título>Teste</título></cabeça>\n<corpo>Teste</corpo>\n</lmht>`;
break;
case 'atualizar':
caminhoVisao = caminho.join(diretorioVisoes, 'atualizar.lmht');
conteudoVisao = `<lmht>\n <cabeça><título>Teste</título></cabeça>\n<corpo>Teste</corpo>\n</lmht>`;
break;
case 'excluir':
caminhoVisao = caminho.join(diretorioVisoes, 'excluir.lmht');
conteudoVisao = `<lmht>\n <cabeça><título>Teste</título></cabeça>\n<corpo>Teste</corpo>\n</lmht>`;
break;
}

sistemaArquivos.writeFileSync(
caminhoVisao,
conteudoVisao
);

return caminhoVisao;
}
5 changes: 5 additions & 0 deletions interface-linha-comando/gerar/tipo-visao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type TipoVisao = 'selecionarTudo' |
'selecionarUm' |
'adicionar' |
'atualizar' |
'excluir';
44 changes: 1 addition & 43 deletions interface-linha-comando/index.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1 @@
import { async as glob } from 'fast-glob'
import sistemaArquivos from 'fs';
import caminho from 'path';

export function criarDiretorioAplicacao(nomeAplicacao: string): string {
const diretorioCompleto = process.cwd() + caminho.sep + nomeAplicacao;
if (!sistemaArquivos.existsSync(nomeAplicacao)) {
sistemaArquivos.mkdirSync(nomeAplicacao);
console.log(`Diretório criado: ${diretorioCompleto}`);
} else {
console.log(`Diretório já existe: ${diretorioCompleto}`);
}

return diretorioCompleto;
}

export async function copiarExemploParaProjeto(tipoDeProjeto: string, diretorioProjeto: string) {
const diretorioExemplos = caminho.join(__dirname, '../exemplos/' + tipoDeProjeto);
const formatoGlob = (diretorioExemplos + '/**/*.{delegua,foles,lmht,md}').replace(/\\/gi, '/');

const arquivos = await glob([formatoGlob], {
dot: true,
absolute: false,
stats: false,
});

return Promise.all(
arquivos.map(async (arquivo) => {
const arquivoResolvido = caminho.resolve(arquivo);
const novoCaminhoArquivo = arquivoResolvido.replace(diretorioExemplos, diretorioProjeto);
console.log(novoCaminhoArquivo);
await sistemaArquivos.promises.mkdir(caminho.dirname(novoCaminhoArquivo), { recursive: true })
return sistemaArquivos.promises.copyFile(arquivoResolvido, novoCaminhoArquivo);
})
);
}

/* export function gerarProjetoPorTipoDeProjeto(tipoDeProjeto: string) {
switch (tipoDeProjeto) {
case 'api-rest':
sistemaArquivos.
}
} */
export * from './novo';
43 changes: 43 additions & 0 deletions interface-linha-comando/novo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { async as glob } from 'fast-glob'
import sistemaArquivos from 'fs';
import caminho from 'path';

export function criarDiretorioAplicacao(nomeAplicacao: string): string {
const diretorioCompleto = process.cwd() + caminho.sep + nomeAplicacao;
if (!sistemaArquivos.existsSync(nomeAplicacao)) {
sistemaArquivos.mkdirSync(nomeAplicacao);
console.log(`Diretório criado: ${diretorioCompleto}`);
} else {
console.log(`Diretório já existe: ${diretorioCompleto}`);
}

return diretorioCompleto;
}

export async function copiarExemploParaProjeto(tipoDeProjeto: string, diretorioProjeto: string) {
const diretorioExemplos = caminho.join(__dirname, '../exemplos/' + tipoDeProjeto);
const formatoGlob = (diretorioExemplos + '/**/*.{delegua,foles,lmht,md}').replace(/\\/gi, '/');

const arquivos = await glob([formatoGlob], {
dot: true,
absolute: false,
stats: false,
});

return Promise.all(
arquivos.map(async (arquivo) => {
const arquivoResolvido = caminho.resolve(arquivo);
const novoCaminhoArquivo = arquivoResolvido.replace(diretorioExemplos, diretorioProjeto);
console.log(novoCaminhoArquivo);
await sistemaArquivos.promises.mkdir(caminho.dirname(novoCaminhoArquivo), { recursive: true })
return sistemaArquivos.promises.copyFile(arquivoResolvido, novoCaminhoArquivo);
})
);
}

/* export function gerarProjetoPorTipoDeProjeto(tipoDeProjeto: string) {
switch (tipoDeProjeto) {
case 'api-rest':
sistemaArquivos.
}
} */
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"dependencies": {
"@designliquido/delegua-node": "^0.29.1",
"@designliquido/flexoes": "^0.0.0",
"@designliquido/flexoes": "^0.0.1",
"@designliquido/foles": "^0.6.1",
"@designliquido/lincones-sqlite": "^0.0.2",
"@designliquido/lmht-js": "^0.4.4",
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -325,10 +325,10 @@
esprima "^4.0.1"
lodash.clonedeep "^4.5.0"

"@designliquido/flexoes@^0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@designliquido/flexoes/-/flexoes-0.0.0.tgz#7f9b9cb60804db898023c45325de5dcfbb1fd98c"
integrity sha512-G0KGAj/GyFO3SPVvnAHlPl9PdEHuqPO0jm9VDCtZOlnV9wYKAj1NKlWvS4RDdOeLLhNH8cOBMccjIxWjwGFQuw==
"@designliquido/flexoes@^0.0.1":
version "0.0.1"
resolved "https://registry.yarnpkg.com/@designliquido/flexoes/-/flexoes-0.0.1.tgz#7e98904dbb4aec2cabc1c0879fe57b2015ef4604"
integrity sha512-zbl8Vofb4Dh97SiMyvjwLMfFaBRnUPuL9mJkj7REHWwcWxAxKMrnjLfpBtBfGg46Rq6R1XRFcV3IWWp9y4w4IA==

"@designliquido/foles@^0.6.1":
version "0.6.1"
Expand Down

0 comments on commit 9ae3e16

Please sign in to comment.