Primeiros passos: desenvolvimento local
Crie um aplicativo local, faça uma requisição autenticada e leia suas próprias linhas com RLS do PostgreSQL. Para HTTPS em produção, use Implantação.
Você precisa de Docker, curl e jq. O cliente JavaScript opcional exige Node 22+; o desenvolvimento do cliente Rust exige Rust 1.88+. Compilar o servidor a partir da fonte exige o Rust 1.99.0 fixado no projeto. O binário não precisa de Node em execução.
1. Instale o binário
No Linux com Docker já instalado:
curl -fsSL https://raw.githubusercontent.com/Nelcota/Nelcota/main/scripts/install.sh | NELCOTA_SKIP_DOCKER=1 sh
nelcota --versionIsso instala a versão publicada mais recente, atualmente 0.4.0. Para compilar essa versão no macOS/Windows com Rust 1.99+:
cargo install --locked --git https://github.com/Nelcota/Nelcota --tag v0.4.0 nelcota-serverPara este checkout, execute cargo build --locked -p nelcota-server e use o caminho absoluto de target/debug/nelcota no lugar de nelcota. Recursos não publicados estão no changelog do servidor. Veja Notes staging para validar separadamente versões publicadas e candidatas.
2. Inicie o ambiente de desenvolvimento
Use um diretório novo para o aplicativo, fora do repositório do Nelcota:
mkdir notes-app && cd notes-app
nelcota devO comando inicia PostgreSQL 17 em nelcota-dev-postgres-54322, mantém os dados em um volume Docker, aplica migrações internas e serve a API em primeiro plano. A API fica em http://127.0.0.1:8000, e o painel em /admin/. Sua conta é admin@localhost; leia ADMIN_PASSWORD localmente em .nelcota/dev.env. Não compartilhe esse arquivo.
Senhas do banco, chaves de assinatura e credenciais do painel permanecem nesse arquivo legível pelo proprietário e ignorado pelo Git. Repetir dev reutiliza esses valores. Use --listen 127.0.0.1:9000 ou --db-port 54323 para portas livres; mudar a porta do banco seleciona outro contêiner/volume, sem mover os dados. Ctrl+C para a API; o contêiner do banco e seus dados permanecem até você pará-los/removê-los.
dev ativa armazenamento em disco e deixa SMTP/confirmação de email desativados. O cadastro retorna uma sessão imediatamente. Ele usa configurações geradas, não as substituições do .env do aplicativo.
3. Escreva uma migração
Mantenha dev em execução. Abra outro terminal em notes-app. Este arquivo contém o schema dos exemplos dos SDKs, incluindo extra e o bucket privado files. Faça isso uma vez em um banco novo:
mkdir -p migrations src
cat > migrations/V1__notes.sql <<'SQL'
CREATE TABLE public.notes (
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
owner uuid NOT NULL DEFAULT auth.uid(),
body text NOT NULL,
extra jsonb,
created_at timestamptz NOT NULL DEFAULT now()
);
ALTER TABLE public.notes ENABLE ROW LEVEL SECURITY;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.notes TO authenticated;
CREATE POLICY notes_owner ON public.notes FOR ALL TO authenticated
USING (owner = auth.uid()) WITH CHECK (owner = auth.uid());
INSERT INTO storage.buckets (id, public) VALUES ('files', false);
CREATE POLICY notes_files_owner ON storage.objects FOR ALL TO authenticated
USING (bucket_id = 'files' AND (storage.foldername(name))[1] = auth.uid()::text)
WITH CHECK (bucket_id = 'files' AND (storage.foldername(name))[1] = auth.uid()::text);
SQLPara um schema existente, use examples/notes.sql, que pode ser repetido, ou uma nova migração adicionando colunas ausentes. CREATE TABLE IF NOT EXISTS não adiciona colunas a uma tabela existente. Um GRANT permite uma operação, RLS ativa a filtragem de linhas, e uma política define as linhas acessíveis.
4. Aplique a migração
nelcota migrate
nelcota migrateA primeira execução aplica o arquivo e registra seu checksum em nelcota.user_migrations; a segunda não altera nada. A API recarrega seu catálogo sem reiniciar. Nunca edite uma migração aplicada: adicione V2__.... O migrations/ da raiz do repositório contém SQL interno, não o schema do aplicativo.
5. Gere os tipos
nelcota types -o src/database.ts
nelcota types --lang rust -o src/database.rsGere novamente após alterações no schema. Os geradores descrevem o schema do servidor em execução; compilar o consumidor não conecta ao seu banco.
6. Use o cliente
Primeiro faça uma requisição autenticada usando apenas curl e jq:
O catálogo recarrega de forma assíncrona após a migração. A leitura limitada abaixo aguarda notes antes de enviar uma escrita; um erro diferente de 404 interrompe o exemplo. Mutações são enviadas uma vez.
set -eu
SESSION=$(curl -fsS -X POST http://127.0.0.1:8000/auth/v1/signup \
-H 'content-type: application/json' \
-d '{"email":"[email protected]","password":"a-development-password"}')
TOKEN=$(printf '%s' "$SESSION" | jq -er '.access_token')
NELCOTA_SCHEMA_READY=0
for attempt in 1 2 3 4 5 6 7 8 9 10; do
NELCOTA_READ_STATUS=$(curl -sS -o /dev/null -w '%{http_code}' \
http://127.0.0.1:8000/rest/v1/notes -H "authorization: Bearer $TOKEN")
if [ "$NELCOTA_READ_STATUS" = 200 ]; then NELCOTA_SCHEMA_READY=1; break; fi
[ "$NELCOTA_READ_STATUS" = 404 ] || { printf '%s\n' 'Readiness request failed' >&2; exit 1; }
sleep 0.2
done
[ "$NELCOTA_SCHEMA_READY" = 1 ] || { printf '%s\n' 'Schema is not ready' >&2; exit 1; }
curl -fsS -X POST http://127.0.0.1:8000/rest/v1/notes \
-H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
-H 'prefer: return=representation' -d '{"body":"My first note"}'
curl -fsS 'http://127.0.0.1:8000/rest/v1/notes?order=id.desc' \
-H "authorization: Bearer $TOKEN"Use essa senha apenas no exemplo local. Se a conta existir, entre com POST /auth/v1/token?grant_type=password e o mesmo JSON, em vez de cadastrar novamente. O token de outro usuário não retorna nenhuma nota de Ana. Se o projeto exige confirmação, confirme o email e entre antes de extrair um token de acesso.
Para um cliente JavaScript executável, instale o pacote publicado:
npm init -y
npm install @nelcota/[email protected]
cat > client.mjs <<'JS'
import { createClient, unwrap } from '@nelcota/client';
const client = createClient('http://127.0.0.1:8000');
try {
unwrap(await client.auth.signInWithPassword({
email: '[email protected]', password: 'a-development-password',
}));
const { data } = await client.from('notes').select('id,body,created_at')
.order('id', { ascending: false }).throwOnError();
console.log(data);
} finally { client.dispose(); }
JS
node client.mjsEm um aplicativo TypeScript, importe Database do arquivo gerado e use createClient<Database>(url) com a configuração de compilação TypeScript do seu framework. O SDK TypeScript explica diferenças entre pacote publicado e fonte. O SDK Rust usa o mesmo schema Notes.
Aviso:
service_roleignora RLS. Nunca o use em um navegador ou cliente móvel; use o token de acesso de cada usuário.
Solução de problemas
Se as portas estiverem ocupadas, escolha portas livres para a API/banco antes de iniciar. Para user_already_exists, entre na conta existente. Para linhas vazias, 401/403 ou colunas ausentes, veja Resolver problemas. Criar apenas .env não configura nelcota serve: ele lê variáveis do processo e TOML opcional. Compose/systemd do host e dev carregam suas próprias configurações.
Próximos passos
- Sintaxe de consultas e erros: API REST.
- Arquivos e políticas: Armazenamento.
- SDKs: TypeScript e Rust.
- Produção: Implantação. Verificações de instalação/reinício: Notes staging.