Conjunto de ferramentas para desenvolvimento de aplicações para a internet 100% em português.
- Delégua é uma linguagem de programação 100% em português;
- Pituguês é uma linguagem de programação 100% em português com sintaxe baseada em indentação, inspirada em Python;
- LMHT é uma linguagem de marcação 100% em português, feita para estruturar páginas de internet;
- FolEs é uma linguagem para folhas de estilo, que estilizam páginas de internet.
Liquido é um ferramentário que combina essas linguagens para ser possível desenvolver para a internet 100% em português.
Você deve ter o Node.js instalado.
Depois de instalar no Node.js, execute o seguinte comando no diretório em que seu projeto está:
npm i liquidoSe preferir usar o Yarn ao invés do NPM, use:
yarn add liquidoIsso deve criar um arquivo package.json com algumas informações de dependências. Neste arquivo, adicione o seguinte:
"scripts": {
"liquido": "node ./node_modules/liquido/index.js"
}E então execute com:
yarn liquidoSe quiser usar liquido com o nodemon para que a aplicação seja recarregada toda vez que houver alteração nos fontes, primeiro instale o nodemon:
npm install -g nodemonModifique seu script para o seguinte:
"scripts": {
"liquido": "nodemon ./node_modules/liquido/index.js"
}Você pode começar seu primeiro projeto do zero, criando todos os arquivos e diretórios manualmente, ou pode utilizar o modo ILC (Interface por Linha de Comando, ou CLI, em inglês) para gerar uma estrutura básica de arquivos e diretórios.
Para gerar um novo projeto, utilize o comando:
npx liquido novo [nome-do-projeto]nome-do-projeto é opcional. Se não for fornecido, a interface deverá perguntar pelo nome do projeto.
Crie no seu projeto um diretório chamado rotas. Depois, crie dentro de rotas um arquivo chamado inicial.delegua.
Dentro de inicial.delegua, adicione o seguinte:
liquido.rotaGet(funcao(requisicao, resposta) {
resposta.enviar("Olá mundo").status(200)
})Execute liquido usando o seguinte comando:
yarn liquidoOu, se preferir o NPM:
npm run liquidoIsso deve iniciar um servidor HTTP na porta 3000. Experimente entrar em http://localhost:3000. A mensagem "Olá mundo" deve aparecer.
Para usar Pituguês, defina liquido.linguagem = 'pituguês' no arquivo de configuração (veja a seção Configuração). Crie um diretório chamado rotas e dentro dele um arquivo chamado inicial.pitu.
Em Pituguês, as rotas são registradas por meio de decoradores acima da declaração da função:
@liquido.rotaGet("/")
funcao minha_rota_get(requisicao, resposta):
resposta.enviar("Olá mundo").status(200)Execute liquido normalmente com yarn liquido ou npm run liquido. A mensagem "Olá mundo" deve aparecer ao acessar http://localhost:3000.
A maior inspiração deste projeto é a FastAPI, mas também há influência de:
Algumas ideias retiradas desses projetos:
- Rotas montadas por convenção: garante coesão do projeto por design, assim como facilita a validação das lógicas das rotas declaradas. Também garante um crescimento natural do projeto de forma ordenada;
- Mínimo de código escrito: programação deve ser uma experiência incrível para cada desenvolvedor, e o conjunto de ferramentas deve colaborar com isso. A inicialização deve ser muito simples e muito rápida, mas o processo não pode ser muito mágico: o desenvolvedor deve ser capaz de compreender facilmente como as coisas funcionam;
- Foco nos fundamentos: como servidores HTTP funcionam, quais são as premissas de REST, o que está por trás de cada tecnologia;
- Auto-descoberta de componentes: o ferramentário deve ser capaz de descobrir o que está habilitado no projeto olhando alguns arquivos e diretórios, e inicializando tudo isso automaticamente.
Para uma implementação inicial, foram escolhidas bibliotecas consagradas do Node.js de desenvolvimento para a Internet:
- Express, um servidor HTTP;
- Nodemon, um observador de sistema de arquivos que recarrega a aplicação quando há mudanças em certos arquivos e/ou diretórios;
- Handlebars, um sistema de templates;
- Helmet, um middleware para Express.js que define várias configurações de cabeçalho de requisições e respostas que, via de regra, deixam a aplicação mais segura;
- Morgan, um middleware para estenografia de requisições HTTP, enviando mensagens úteis para desenvolvedores em console;
- Cors, um middleware para restringir certas origens de enviar requisições para a aplicação em liquido. É considerado um requisito essencial de segurança;
- Passport, um middleware básico de autenticação;
- Cookie Parser, um middleware para interpretação de cookies que venham em requisições.
Liquido instancia os componentes básicos de Delégua ou Pituguês (conforme a configuração) e os controla, instrumentando instruções escritas nessas linguagens para JavaScript puro. Isso garante a acessibilidade de se programar em português com o mínimo de impacto no desempenho da aplicação como um todo, além da eliminação da complexidade de se implementar tudo dentro de cada linguagem.
Toda e qualquer rota deve ficar em um diretório rotas. O arquivo padrão depende da linguagem configurada:
| Linguagem | Extensão | Arquivo padrão |
|---|---|---|
| Delégua | .delegua |
inicial.delegua |
| Pituguês | .pitu |
inicial.pitu |
Se queremos criar uma rota na raiz do site, podemos criar um arquivo inicial.delegua com o seguinte:
liquido.rotaGet(funcao(requisicao, resposta) {
resposta.enviar("Olá mundo").status(200)
})Em Pituguês, as rotas são declaradas com decoradores seguidos da definição da função:
@liquido.rotaGet("/")
funcao minha_rota_get(requisicao, resposta):
resposta.enviar("Olá mundo").status(200)A instrução acima registra uma rota HTTP GET em "/" (por exemplo, http://localhost:3000/) que responde com um texto "Olá mundo" e o status HTTP 200.
Se queremos uma rota http://localhost:3000/teste, podemos fazer de duas formas:
- Em Delégua: criar um arquivo
teste.deleguaem/rotas, ou um diretóriotestecominicial.deleguadentro. - Em Pituguês: criar um arquivo
teste.pituem/rotas, ou um diretóriotestecominicial.pitudentro.
Assim como para o diretório rotas, todo e qualquer diretório dentro de rotas também tem como arquivo padrão o inicial.delegua (Delégua) ou inicial.pitu (Pituguês).
Cada arquivo só pode ter uma chamada por método HTTP de rota. Por exemplo, um arquivo não pode ter duas chamadas a liquido.rotaGet(). Nada impede um arquivo de ter uma chamada para cada tipo de rota. Os métodos são:
liquido.rotaGet()liquido.rotaPost()liquido.rotaPut()liquido.rotaDelete()liquido.rotaPatch()liquido.rotaCopy()liquido.rotaHead()liquido.rotaOptions()liquido.rotaPurge()liquido.rotaLock()liquido.rotaUnlock()liquido.rotaPropfind()
Algumas rotas ainda não são suportadas porque o Express.js 4 não as implementou, mas estão marcadas para implementações futuras (Express.js 5, que ainda é beta). São elas:
liquido.rotaLink()liquido.rotaUnlink()liquido.rotaView()
Liquido procura por um arquivo chamado configuracao.delprops na raiz do seu projeto. Nele ficam as configurações globais da aplicação.
A propriedade liquido.linguagem define qual linguagem de back-end será usada. Os valores aceitos são 'delegua' (padrão) e 'pituguês'.
Um exemplo de configuracao.delprops para um projeto em Delégua:
liquido.arquetipo = 'rest'
liquido.linguagem = 'delegua'
liquido.roteador.cors = verdadeiro
liquido.roteador.bodyParser = verdadeiro
liquido.roteador.morgan = verdadeiro
liquido.roteador.cookieParser = verdadeiro
liquido.roteador.passport = verdadeiro
liquido.roteador.json = verdadeiro
liquido.roteador.helmet = verdadeiroPara usar Pituguês, basta alterar a propriedade linguagem:
liquido.arquetipo = 'rest'
liquido.linguagem = 'pituguês'
liquido.roteador.cors = verdadeiro
liquido.roteador.bodyParser = verdadeiro
liquido.roteador.morgan = verdadeiro
liquido.roteador.cookieParser = verdadeiro
liquido.roteador.passport = falso
liquido.roteador.json = verdadeiro
liquido.roteador.helmet = verdadeiroUma aplicação em Liquido pode servir arquivos estáticos se o roteador tiver uma configuração de diretório correspondente. Por exemplo:
liquido.roteador.diretorioEstatico = 'publico'Ou seja, havendo um diretório publico na sua aplicação, é possível servir arquivos como imagens, CSS, JS e assim por diante.
Se uma imagem com o nome teste.png é colocada dentro do diretório publico, ao iniciar sua aplicação em http://localhost:3000, a imagem pode ser acessada por http://localhost:3000/teste.png.
Ao inicializar, Liquido verifica um diretório estilos. Havendo arquivos FolEs nele (extensão .foles), cada arquivo é automaticamente convertido para CSS e salvo em um diretório dentro do diretório estático definido na configuração chamado css. Ou seja, um arquivo teste.foles é salvo em /publico/css/teste.css e pode ser acessado por http://localhost:3000/css/teste.css.
Liquido foi pensado para servir qualquer padrão de projeto para aplicações Web. A primeira versão de Liquido garante a implementação dos seguintes padrões:
- MVC (Modelo, Visão, Controle): padrão em três camadas em que o servidor normalmente devolve HTML;
- RESTful API: Padrão em que a aplicação funciona como um serviço não visual, normalmente retornando dados serializáveis como JSON e XML.
Futuras versões de Liquido terão:
- GraphQL
- gRPC
O comando liquido banco iniciar inicializa a estrutura e os dados de um banco de dados a partir do projeto atual. Ele lê as configurações de configuracao.delprops para saber qual tecnologia e caminho usar.
Antes de utilizar este comando, certifique-se de que o arquivo de configuração contém as seguintes propriedades:
liquido.dados.lincones.tecnologia = 'sqlite'
liquido.dados.lincones.caminho = 'banco.db'Por padrão, ou quando liquido.dados.motor = 'lincones' estiver definido, o comando lê um script LinConEs na raiz do projeto. O nome padrão do arquivo é inicializacao.lincones, e os enunciados devem ser separados por ponto-e-vírgula (;):
CRIAR TABELA usuarios (
ID INTEIRO NAO NULO CHAVE PRIMARIA AUTO INCREMENTO,
NOME TEXTO NAO NULO,
EMAIL TEXTO NAO NULO
);
INSERIR EM usuarios (NOME, EMAIL) VALORES ('Administrador', 'admin@exemplo.com')Para executar com o nome padrão:
npx liquido banco iniciarPara usar um arquivo diferente:
npx liquido banco iniciar --arquivo meu-script.linconesPara executar apenas a estrutura (enunciados DDL como CRIAR TABELA, ALTERAR TABELA, REMOVER TABELA):
npx liquido banco iniciar --apenas-estruturaPara executar apenas dados (enunciados DML como INSERIR, ATUALIZAR, EXCLUIR, SELECIONAR):
npx liquido banco iniciar --apenas-dadosSe o seu projeto utiliza o pacote @designliquido/delegua-entidades para gerenciamento de esquema e semeadura, configure o motor no arquivo de configuração:
liquido.dados.motor = 'delegua-entidades'
liquido.dados.lincones.tecnologia = 'sqlite'
liquido.dados.lincones.caminho = 'banco.db'Instale o pacote como dependência do seu projeto:
npm install @designliquido/delegua-entidadesO comando liquido banco iniciar irá:
- Escanear o diretório
migracoes/em ordem alfabética, importar cada arquivo e executar a migração que ele exporta como padrão; - Escanear o diretório
sementes/em ordem alfabética, importar cada arquivo e executar as sementes que ele exporta como padrão.
Cada arquivo de migração deve exportar uma instância de Migracao como exportação padrão:
// migracoes/001-criar-usuarios.js
const { Migracao } = require('@designliquido/delegua-entidades');
module.exports = new Migracao('001', 'Criar tabela de usuários')
.criarTabela('usuarios', [
{ nomeColuna: 'id', tipo: 'INTEIRO', nulo: false, chavePrimaria: true, autoIncremento: true },
{ nomeColuna: 'nome', tipo: 'TEXTO', nulo: false },
{ nomeColuna: 'email', tipo: 'TEXTO', nulo: false }
]);Com --apenas-estrutura, apenas as migrações são executadas. Com --apenas-dados, apenas as sementes são executadas.
Quando o banco de dados usa :memory: (ou qualquer outro caminho), é possível inicializá-lo automaticamente toda vez que o servidor Líquido é iniciado. Para isso, defina liquido.dados.lincones.autoInicializar = verdadeiro no arquivo configuracao.delprops:
liquido.dados.lincones.tecnologia = 'sqlite'
liquido.dados.lincones.caminho = ':memory:'
liquido.dados.lincones.autoInicializar = verdadeiroCom essa configuração, ao executar npx liquido, o script inicializacao.lincones será executado automaticamente antes de o servidor começar a aceitar requisições. Se a inicialização falhar, uma advertência é exibida no console e o servidor continua funcionando normalmente.
Por padrão, o arquivo de script utilizado é inicializacao.lincones. Para usar um arquivo diferente, defina a chave arquivoInicializacao:
liquido.dados.lincones.autoInicializar = verdadeiro
liquido.dados.lincones.arquivoInicializacao = 'banco-inicial.lincones'Importante: Quando
autoInicializarestá ativo, o Líquido reutiliza a mesma conexão com o banco de dados tanto para a inicialização quanto para as requisições. Isso é necessário para que bancos em memória (:memory:) compartilhem os dados entre inicialização e rotas.
Liquido permite a qualquer desenvolvedor que saiba português a escrever aplicações Web, e possivelmente criar um ecossistema profissional a partir dele. Procuramos traduzir o máximo possível de informações e conceitos por uma questão de acessibilidade, mas há limites para isso. Por exemplo, não traduzimos os métodos de HTTP porque entendemos que uma tradução disso implicaria em um protocolo novo de transferência.
O que tentamos fazer é instigar os desenvolvedores a aprenderem inglês conforme vão dominando outros conceitos. Um aprendizado direcionado de inglês é muito mais eficiente do que o aprendizado da língua por si só, sem um objetivo no horizonte.