Skip to content

entrega teste#87

Open
alves-felipe wants to merge 1 commit into
corelabbr:mainfrom
alves-felipe:main
Open

entrega teste#87
alves-felipe wants to merge 1 commit into
corelabbr:mainfrom
alves-felipe:main

Conversation

@alves-felipe

@alves-felipe alves-felipe commented Sep 10, 2025

Copy link
Copy Markdown
  • criação do model card;
  • adicionando docker-compose

como executar:

fontend e a api deven estar no mesmo diretório

|- web
|- api

ir até o diretório /dev da api

executar: docker-compose up -d corelab-mysql

após subir o mysql: docker-compose up -d

Summary by CodeRabbit

  • New Features

    • Added Cards REST API (list, view, create, update, delete).
    • Enabled database migrations, rollbacks, seeding, and model scaffolding via CLI commands.
  • Chores

    • Integrated ORM and MySQL driver; configured MySQL connection.
    • Added development Docker Compose for frontend, backend, and database.
  • Documentation

    • Introduced guidelines for creating model cards and using docker-compose in pull requests.

@coderabbitai

coderabbitai Bot commented Sep 10, 2025

Copy link
Copy Markdown

Walkthrough

Adds Card CRUD feature using AdonisJS Lucid (model, controller, routes, migration), configures MySQL database and dev Docker Compose, updates TypeScript typings and dependencies, introduces extensive Lucid-related CLI commands via ace-manifest, and adds a pull request guidance document.

Changes

Cohort / File(s) Summary
Documentation
PULL_REQUEST.md
New doc with instructions for model card creation and docker-compose usage/order.
CLI Commands (Lucid)
ace-manifest.json
Adds 13 Lucid CLI commands (db:seed/wipe/truncate, make:*, migration:*) with args/flags and loadApp settings.
Cards Feature (API + ORM + Migration + Routes)
app/Controllers/CardsController.ts, app/Models/Card.ts, database/migrations/1757119501752_cards.ts, start/routes.ts
Implements Card CRUD: model fields (id, title, note, color, is_favorite, timestamps), REST controller (index/getById/store/update/destroy), migration creating cards table, and routes for /card endpoints.
Database Configuration
config/database.ts
New MySQL database config using Env-driven settings; sets defaults for migrations, healthCheck, and debug.
Dev Environment (Docker)
dev/docker-compose.yml
New compose with MySQL, frontend, backend services; env vars and commands for local development.
Dependencies
package.json
Adds @adonisjs/lucid, luxon, mysql2 to dependencies.
TypeScript Typings/Format
tsconfig.json
Adds @adonisjs/lucid to compilerOptions.types; formatting adjustments only elsewhere.
Factories Placeholder
database/factories/index.ts
Adds commented Factory import line; no functional change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Router
  participant CardsController
  participant Lucid as Lucid ORM
  participant DB as MySQL

  rect rgba(230,240,255,0.5)
  Note over Client,DB: List Cards (GET /card)
  Client->>Router: GET /card
  Router->>CardsController: index()
  CardsController->>Lucid: Card.all()
  Lucid->>DB: SELECT * FROM cards
  DB-->>Lucid: rows
  Lucid-->>CardsController: Card[]
  CardsController-->>Client: 200 JSON (cards)
  end

  rect rgba(230,255,230,0.5)
  Note over Client,DB: Create Card (POST /card)
  Client->>Router: POST /card {title,note,color,is_favorite}
  Router->>CardsController: store(req)
  CardsController->>Lucid: Card.create(payload)
  Lucid->>DB: INSERT INTO cards (...)
  DB-->>Lucid: inserted row
  Lucid-->>CardsController: Card
  CardsController-->>Client: 201 JSON (card)
  end

  rect rgba(255,245,230,0.6)
  Note over Client,DB: Get/Update/Delete by id
  Client->>Router: GET/PUT/DELETE /card/:id
  Router->>CardsController: getById/update/destroy
  alt findOrFail
    CardsController->>Lucid: Card.findOrFail(id)
    Lucid->>DB: SELECT ... WHERE id=?
    DB-->>Lucid: row or none
    Lucid-->>CardsController: Card or throws
  else not found
    CardsController-->>Client: 404 error
  end
  opt update
    CardsController->>Lucid: card.merge(body).save()
    Lucid->>DB: UPDATE cards SET ...
    DB-->>Lucid: ok
    CardsController-->>Client: 200 JSON (card)
  end
  opt destroy
    CardsController->>Lucid: card.delete()
    Lucid->>DB: DELETE FROM cards WHERE id=?
    DB-->>Lucid: ok
    CardsController-->>Client: 200/204
  end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I hop through fields of code so wide,
A deck of Cards now by my side.
Migrations bloom, the seeds all sow,
Lucid rivers start to flow.
Docker hums a steady tune—
MySQL moons, we ship by noon. 🐇✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
PULL_REQUEST.md (1)

1-16: Fix typos and clarify run instructions (Portuguese), align naming with docker-compose

Spelling (“fontend”/“deven”), casing, and directory names diverge from compose paths. Suggest clearer, copy‑pasteable steps and Compose v2 syntax.

Apply:

- - criação do model card;
- - adicionando docker-compose
-
- como executar:
-
- fontend e a api deven estar no mesmo diretório
-
- |- web
- |- api
-
- ir até o diretório /dev da api
-
- executar: docker-compose up -d corelab-mysql
-
- após subir o mysql: docker-compose up -d
+ - Criação do model Card
+ - Adição do docker-compose de desenvolvimento
+
+ Como executar:
+
+ Frontend e API devem estar no mesmo diretório:
+
+ ├─ web
+ └─ api
+
+ Acesse o diretório /dev da API:
+ 
+   cd api/dev
+
+ Suba primeiro o MySQL:
+ 
+   docker compose up -d corelab-mysql
+
+ Após o MySQL estar saudável, suba os demais serviços:
+ 
+   docker compose up -d
+
+ Observação: Se sua instalação usa a CLI antiga, substitua “docker compose” por “docker-compose”.
🧹 Nitpick comments (12)
database/factories/index.ts (1)

1-1: Replace commented import with a real Factory or remove dead code

Either implement a Card factory for tests/seeding, or drop the commented import to keep the file clean.

Apply one of the following:

Option A — remove the dead line:

-// import Factory from '@ioc:Adonis/Lucid/Factory'

Option B — implement a Card factory (add dev dep @faker-js/faker if needed):

// database/factories/index.ts
import Factory from '@ioc:Adonis/Lucid/Factory'
import Card from 'App/Models/Card'
import { faker } from '@faker-js/faker'

export const CardFactory = Factory
  .define(Card, ({}) => {
    return {
      title: faker.lorem.words(3),
      note: faker.lorem.sentences(2),
      color: faker.internet.color().toUpperCase(), // e.g. #A1B2C3
      isFavorite: faker.datatype.boolean(),
    }
  })
  .build()
package.json (1)

66-69: Bump engines to Node.js v22 LTS
Node 16 is EOL—update package.json engines to "node": "^22.0.0" (active LTS as of September 10, 2025) and align Docker base images to Node 22 LTS.

database/migrations/1757119501752_cards.ts (2)

10-14: Add constraints and suitable column types (nullable/length/index)

Recommend making title required, allowing long notes, constraining color, and indexing is_favorite if filtered often.

-      table.string('title')
-      table.string('note')
-      table.string('color')
-      table.boolean('is_favorite').defaultTo(false)
+      table.string('title', 150).notNullable()
+      table.text('note') // allows longer content than VARCHAR(255)
+      table.string('color', 7) // e.g. #RRGGBB
+      table.boolean('is_favorite').notNullable().defaultTo(false).index()

18-19: Consider defaults/not-null for timestamps

If records may be inserted outside Lucid, add notNullable and defaults.

-      table.timestamp('created_at', { useTz: true })
-      table.timestamp('updated_at', { useTz: true })
+      table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(this.now())
+      table.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(this.now())
config/database.ts (1)

22-44: Provide safe defaults and ensure numeric port type

Avoid undefined connection and cast port to number for mysql2.

-  connection: Env.get('DB_CONNECTION'),
+  connection: Env.get('DB_CONNECTION', 'mysql'),
@@
-        port: Env.get('MYSQL_PORT'),
+        port: Number(Env.get('MYSQL_PORT', '3306')),
         user: Env.get('MYSQL_USER'),
         password: Env.get('MYSQL_PASSWORD', ''),
         database: Env.get('MYSQL_DB_NAME'),
dev/docker-compose.yml (1)

5-16: Stabilize local dev: healthcheck/depends_on, named volume & Node 20 LTS upgrade

  • Add MySQL healthcheck and make backend depend on it to avoid race conditions.
  • Prefer a named volume (corelab-mysql-data) over a host path for portability.
  • Upgrade to node:20-alpine (AdonisJS v5 requires Node.js ≥ 20) (docs.adonisjs.com) and use npm ci for reproducible installs.
start/routes.ts (2)

26-29: Constrain :id to digits at the routing layer.

Prevents unnecessary controller work and avoids 500s on non-numeric ids.

Apply this diff:

-Route.get('/card/:id', 'CardsController.getById')
+Route.get('/card/:id', 'CardsController.getById').where('id', /^[0-9]+$/)

-Route.put('/card/:id', 'CardsController.update')
+Route.put('/card/:id', 'CardsController.update').where('id', /^[0-9]+$/)

-Route.delete('/card/:id', 'CardsController.destroy')
+Route.delete('/card/:id', 'CardsController.destroy').where('id', /^[0-9]+$/)

25-29: Consider a resourceful route with plural path.

Reduces boilerplate and aligns with REST conventions.

-Route.get('/card', 'CardsController.index')
-Route.get('/card/:id', 'CardsController.getById')
-Route.post('/card', 'CardsController.store')
-Route.put('/card/:id', 'CardsController.update')
-Route.delete('/card/:id', 'CardsController.destroy')
+Route.resource('cards', 'CardsController').apiOnly()

Note: If adopted, rename getById -> show in the controller or map via .only()/.except().

app/Models/Card.ts (2)

5-21: Use declare on model fields to satisfy strict property initialization.

Matches AdonisJS model scaffolding and avoids TS init errors.

-  public id: number
+  public declare id: number
...
-  public title: string
+  public declare title: string
-  public note: string
+  public declare note: string
-  public color: string
+  public declare color: string
-  public is_favorite: boolean
+  public declare is_favorite: boolean
...
-  public createdAt: DateTime
+  public declare createdAt: DateTime
-  public updatedAt: DateTime
+  public declare updatedAt: DateTime

14-15: Optional: prefer camelCase in the API while keeping snake_case in DB.

Expose isFavorite in JSON but keep is_favorite column, improving client DX without schema changes.

-  @column()
-  public is_favorite: boolean
+  @column({ columnName: 'is_favorite', serializeAs: 'isFavorite' })
+  public declare is_favorite: boolean
app/Controllers/CardsController.ts (2)

11-13: Use params instead of request.param for clarity and typing.

Cleaner and idiomatic in Adonis controllers.

-  public async getById({ request }: HttpContextContract) {
-    return await Card.findOrFail(request.param('id'))
-  }
+  public async getById({ params }: HttpContextContract) {
+    return await Card.findOrFail(params.id)
+  }

16-16: Unnecessary explicit type annotation.

Card.create() already returns Promise<Card>. The : Card annotation adds noise.

-    const card: Card = await Card.create(request.all())
+    const card = await Card.create(/* payload */)

(Note: superseded if you apply the validation change above.)

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b174fe6 and 8882afd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (11)
  • PULL_REQUEST.md (1 hunks)
  • ace-manifest.json (1 hunks)
  • app/Controllers/CardsController.ts (1 hunks)
  • app/Models/Card.ts (1 hunks)
  • config/database.ts (1 hunks)
  • database/factories/index.ts (1 hunks)
  • database/migrations/1757119501752_cards.ts (1 hunks)
  • dev/docker-compose.yml (1 hunks)
  • package.json (1 hunks)
  • start/routes.ts (1 hunks)
  • tsconfig.json (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
app/Controllers/CardsController.ts (1)
app/Models/Card.ts (1)
  • Card (4-22)
🪛 Biome (2.1.2)
app/Controllers/CardsController.ts

[error] 5-5: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)

🔇 Additional comments (3)
package.json (1)

58-61: Deps for Lucid/MySQL/Luxon look correct

The additions of @adonisjs/lucid, luxon, and mysql2 align with the ORM/migration usage elsewhere.

tsconfig.json (1)

28-33: LGTM: Lucid typings added

Including @adonisjs/lucid in compilerOptions.types is correct for decorators/ORM types.

ace-manifest.json (1)

98-572: LGTM: Lucid CLI commands registered

The manifest entries match the added ORM/migration features.

Comment on lines +5 to +7
public async index({}: HttpContextContract) {
return await Card.all()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix Biome error: avoid empty object pattern.

public async index({}: HttpContextContract) triggers lint error and can fail CI.

Minimal fix:

-  public async index({}: HttpContextContract) {
+  public async index() {
     return await Card.all()
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async index({}: HttpContextContract) {
return await Card.all()
}
public async index() {
return await Card.all()
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 5-5: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)

🤖 Prompt for AI Agents
In app/Controllers/CardsController.ts around lines 5 to 7, the method signature
uses an empty destructured parameter ({ }: HttpContextContract) which triggers
the Biome lint error; replace the empty object pattern by either removing the
parameter entirely or accepting a named parameter (e.g., ctx:
HttpContextContract) and not destructuring it so the method becomes a valid
signature and continues to return Card.all().

🛠️ Refactor suggestion

Paginate results to prevent unbounded reads.

For large datasets, Card.all() is risky. Paginate with sensible defaults.

-  public async index() {
-    return await Card.all()
-  }
+  public async index({ request }: HttpContextContract) {
+    const page = Number(request.input('page', 1))
+    const perPage = Math.min(Number(request.input('perPage', 20)), 100)
+    return await Card.query().paginate(page, perPage)
+  }

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 Biome (2.1.2)

[error] 5-5: Unexpected empty object pattern.

(lint/correctness/noEmptyPattern)

🤖 Prompt for AI Agents
In app/Controllers/CardsController.ts around lines 5 to 7, replace the unbounded
Card.all() read with a paginated query: accept the HttpContextContract request,
read page and perPage (with sensible defaults, e.g. page=1, perPage=20), coerce
to integers and clamp perPage to a safe max (e.g. 100), then return
Card.query().paginate(page, perPage) (or Card.paginate(page, perPage) depending
on your ORM). Ensure you return the paginator result (items + meta) so clients
can navigate pages.

Comment on lines +15 to +19
public async store({ request }: HttpContextContract) {
const card: Card = await Card.create(request.all())

return card
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate and whitelist input; avoid request.all() (mass-assignment risk).

Current code accepts arbitrary keys (including id, timestamps) from body+querystring.

-  public async store({ request }: HttpContextContract) {
-    const card: Card = await Card.create(request.all())
-
-    return card
-  }
+  public async store({ request, response }: HttpContextContract) {
+    const payload = await request.validate({
+      schema: schema.create({
+        title: schema.string(),
+        note: schema.string.optional(),
+        color: schema.string.optional(),
+        is_favorite: schema.boolean.optional(),
+      }),
+    })
+    const card = await Card.create(payload)
+    return response.status(201).send(card)
+  }

Add this import at the top of the file:

import { schema } from '@ioc:Adonis/Core/Validator'

Comment on lines +25 to +31
public async update({ request }: HttpContextContract) {
let card = await Card.findOrFail(request.param('id'))

card = await card.merge(request.body()).save()

return card
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Safer update with validation and explicit merge.

Avoids mass-assignment and variable reassignment; supports partial updates.

-  public async update({ request }: HttpContextContract) {
-    let card = await Card.findOrFail(request.param('id'))
-
-    card = await card.merge(request.body()).save()
-
-    return card
-  }
+  public async update({ params, request }: HttpContextContract) {
+    const card = await Card.findOrFail(params.id)
+    const payload = await request.validate({
+      schema: schema.create({
+        title: schema.string.optional(),
+        note: schema.string.optional(),
+        color: schema.string.optional(),
+        is_favorite: schema.boolean.optional(),
+      }),
+    })
+    card.merge(payload)
+    await card.save()
+    return card
+  }

Note: If this remains a PUT, consider requiring all fields; otherwise prefer PATCH for partial updates.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async update({ request }: HttpContextContract) {
let card = await Card.findOrFail(request.param('id'))
card = await card.merge(request.body()).save()
return card
}
public async update({ params, request }: HttpContextContract) {
const card = await Card.findOrFail(params.id)
const payload = await request.validate({
schema: schema.create({
title: schema.string.optional(),
note: schema.string.optional(),
color: schema.string.optional(),
is_favorite: schema.boolean.optional(),
}),
})
card.merge(payload)
await card.save()
return card
}
🤖 Prompt for AI Agents
In app/Controllers/CardsController.ts around lines 25 to 31, the current update
handler does an unvalidated mass-assignment and reassigns the card variable;
instead validate the incoming payload (or use a validator class), pick only
allowed/whitelisted fields from request.body() (to avoid mass-assignment), call
card.merge(allowedFields) without reassigning the variable, await card.save(),
and return the original card instance; also decide whether this is a PUT
(require all fields) or switch to PATCH for partial updates and enforce that
contract in the validator.

Comment on lines +33 to +37
public async destroy({ request }: HttpContextContract) {
let card = await Card.findOrFail(request.param('id'))

return await card.delete()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Return 204 on delete instead of the adapter’s delete result.

Hides internals and matches REST conventions.

-  public async destroy({ request }: HttpContextContract) {
-    let card = await Card.findOrFail(request.param('id'))
-
-    return await card.delete()
-  }
+  public async destroy({ params, response }: HttpContextContract) {
+    const card = await Card.findOrFail(params.id)
+    await card.delete()
+    return response.status(204).send(null)
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async destroy({ request }: HttpContextContract) {
let card = await Card.findOrFail(request.param('id'))
return await card.delete()
}
public async destroy({ params, response }: HttpContextContract) {
const card = await Card.findOrFail(params.id)
await card.delete()
return response.status(204).send(null)
}
🤖 Prompt for AI Agents
In app/Controllers/CardsController.ts around lines 33 to 37, the destroy action
currently returns the adapter's delete result; change it to return a 204 No
Content response instead. After finding the card (using findOrFail), call
card.delete() but do not return its result—use the HTTP context response to send
status 204 with no body (e.g., response.status(204).send()) to hide internals
and follow REST conventions. Ensure the method signature includes the response
object from HttpContextContract if not already imported.

Comment thread dev/docker-compose.yml
Comment on lines +68 to +73
- PORT=3333
- HOST=0.0.0.0
- NODE_ENV=development
- APP_KEY=olgJQ1MqRQVt8QSiMY-96Mf-jSLymlU4
- DRIVE_DISK=local
- DB_CONNECTION=mysql

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

⚠️ Potential issue

Do not commit APP_KEY in compose; generate or load from .env

Leaking APP_KEY (even for dev) risks reuse in other envs. Generate at runtime or load from a local .env.

-      - APP_KEY=olgJQ1MqRQVt8QSiMY-96Mf-jSLymlU4
+      # APP_KEY will be generated automatically at container start for dev

Also run key generation before dev:

-    command: sh -c "npm install && npm run dev"
+    command: sh -c "npm install && node ace generate:key --force && npm run dev"

Optionally, load env from a file instead:

    env_file:
      - ../.env
🤖 Prompt for AI Agents
In dev/docker-compose.yml around lines 68 to 73, the APP_KEY value is committed
in the compose file; remove the hard-coded APP_KEY entry and instead either add
an env_file reference (for example point to ../.env) or rely on the host
environment so the key is loaded at container start, and ensure the dev workflow
runs the app key generation step before starting containers (or generates a key
at runtime if appropriate); do not commit any generated or secret key into
source control.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant