Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geração de Visões por linha de comando #31

Merged
merged 3 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading