Aplicação MVC para a disciplina de Desenvolvimento Web (Prof. Marcos Aurélio). Stack: TypeScript (ESM/NodeNext), Express 5, Prisma (SQLite), Twig.
Nota: A camada de View será evoluída depois em sala — este projeto já entrega Models, Controllers e Rotas funcionando (CRUD básico de Posts, Categorias e Tags).
- Node.js 20+
- npm 8+
- SQLite (embutido; o arquivo do banco será
database.sqlitena raiz)
# 1) Clonar o repositório
git clone https://github.com/cai0duque/mvc-atvd.git
cd mvc-atvd
# 2) Instalar dependências
npm install
# 3) Gerar o Prisma Client (necessário para o runtime)
npx prisma generate
# 4) Criar/atualizar o banco de dados (SQLite) com as tabelas do schema
npx prisma migrate dev --name initO
datasourcedo Prisma (emprisma/schema.prisma) aponta parafile:../database.sqlite— ou seja, o banco fica na raiz do projeto comodatabase.sqlite.
# compilar TypeScript para dist/
npm run build
# iniciar servidor (Express 5)
npm start
# → http://localhost:3000- O servidor registra o Twig e procura as views primeiro em
dist/View; se não encontrar, usasrc/Viewautomaticamente. - Rotas principais estão listadas mais abaixo.
# recompila continuamente
npm run dev| Método | Rota | Descrição |
|---|---|---|
| GET | / |
Home (IndexController) |
| GET | /posts |
Lista posts (PostsController) |
| GET | /post/:id |
Exibe 1 post (PostController) |
| GET | /post/create |
Form de criação de post (Twig) |
| POST | /post/create |
Cria post |
| GET | /user |
Lista usuários (UserController) |
| GET | /category |
Lista categorias (JSON) |
| GET | /category/:id |
Posts da categoria por id (JSON) |
| GET | /category/slug/:slug |
Posts da categoria por slug (JSON) |
| POST | /category/create |
Cria categoria (JSON) |
| GET | /tag |
Lista tags (JSON) |
| POST | /tag/create |
Cria tag (JSON) |
Views Twig incluídas:
src/View/index.twig,post.twig,user.twig,layout.twig,post/form.twig. Categorias e Tags hoje respondem JSON (views serão trabalhadas em sala).
- Crie
src/seed.ts:
import pkg from "@prisma/client";
const { PrismaClient } = pkg;
const prisma = new PrismaClient();
await prisma.user.create({ data: { nome: "Caio" } });
const cat = await prisma.category.create({ data: { nome: "Geral", slug: "geral" } });
const auth = await prisma.author.create({ data: { nome: "Autor Padrão" } });
const tag = await prisma.tag.create({ data: { nome: "TypeScript", slug: "ts" } });
await prisma.post.create({
data: {
titulo: "Primeiro post",
conteudo: "Olá, mundo!",
userId: 1,
categoryId: cat.id,
authorId: auth.id,
tags: { connect: [{ id: tag.id }] },
},
});
await prisma.$disconnect();
console.log("✅ Seed ok");- Adicione o script no
package.json:
{
"scripts": {
"build": "tsc",
"start": "node dist/main.js",
"seed": "npm run build && node dist/seed.js",
"dev": "tsc -w"
}
}- Execute:
npm run seed
npm startNecessário ter ao menos 1
Userno banco (crie via Opção A ou Prisma Studio).
Criar categoria:
curl -X POST http://localhost:3000/category/create \
-H "Content-Type: application/json" \
-d '{"nome":"Tutoriais","slug":"tutoriais"}'Criar tag:
curl -X POST http://localhost:3000/tag/create \
-H "Content-Type: application/json" \
-d '{"nome":"Node","slug":"node"}'Criar post (via formulário): acesse http://localhost:3000/post/create.
npx prisma studio-
AbstractModelcomload(where),save(),delete(). -
Post,User,Category,Author,Tag(helpersfindAll,findById,create,update,destroy). -
Schema Prisma:
Post→userId(obrigatório),categoryId?,authorId?,tags(N-N).- Índices únicos em
Category.slugeTag.slug.
- Base
AbstractControllercomexecute(),getParams(),getMethod(),render/json/redirect. IndexController,PostsController,PostController,UserController.Post/CreateController,Category/CategoryController,Category/CreateController,Tag/TagController,Tag/CreateController.
- Todas as rotas configuradas em
src/main.ts(Express 5, ESM/NodeNext, Twig viacreateRequire).
-
ESM/NodeNext: imports relativos precisam terminar com
.jsnos arquivos.ts(ex.:import X from "./foo.js"). -
Prisma Client não encontrado / named export: rode
npx prisma generate. Em ESM, o padrão usado é:import pkg from "@prisma/client"; const { PrismaClient } = pkg;
-
Views não encontradas: se der
Failed to lookup view .../dist/View, o projeto já usa fallback parasrc/View. Verifique se os.twigestão emsrc/View. -
Porta em uso: mude a porta via
PORT=4000 npm start(Linux/Mac) ouset PORT=4000 && npm start(Windows PowerShell).
# abrir Prisma Studio
npx prisma studio
# rebuild limpo (Windows PowerShell)
if (Test-Path dist) { Remove-Item -Recurse -Force dist }
npm run build && npm start- ✅
AbstractModelcomload/save/delete. - ✅
AbstractControllercomexecute/getParams/getMethod. - ✅ Models
Category,Author,Tag(além dePosteUser). - ✅ Controllers pedidos implementados.
- ✅ Rotas criadas e respondendo.
- ✅ Código organizado (TypeScript + ESM), comentários pontuais.
- ✅ Repositório público no GitHub.