Skip to content

CRUD completo#75

Open
DevRubens wants to merge 2 commits into
corelabbr:mainfrom
DevRubens:main
Open

CRUD completo#75
DevRubens wants to merge 2 commits into
corelabbr:mainfrom
DevRubens:main

Conversation

@DevRubens

@DevRubens DevRubens commented Aug 28, 2025

Copy link
Copy Markdown

CRUD completo + filtros

Summary by CodeRabbit

  • New Features
    • Tasks REST API: CRUD, search (q), favorite filter, predefined colors, validators, and proper HTTP statuses; root health-check.
  • Database
    • PostgreSQL setup with tasks table and native enum-backed color column; migration included.
  • CLI
    • New commands for models, migrations, seeders, factories, and DB management.
  • Configuration
    • Updated .env example with DB settings and placeholder APP_KEY.
  • Documentation
    • README replaced with API-first Tasks API (Portuguese).

CRUD completo + filtros
@coderabbitai

coderabbitai Bot commented Aug 28, 2025

Copy link
Copy Markdown

Walkthrough

Adds AdonisJS Lucid integration: DB config, migration, Task model, validators, controllers, REST routes, CLI/ace updates and manifest entries, environment example changes, dependency updates, and README replacement for a Tasks API. Config namespace and providers updated.

Changes

Cohort / File(s) Summary
Adonis config
\.adonisrc.json
Adds Lucid to providers; updates commands entries to include Lucid commands and adjust core command path; changes httpControllers namespace to App/Controllers/Http.
Bootstrap & CLI
ace, ace-manifest.json
Adds shebang and source-map register; updates Ignitor import/invocation in ace; expands ace-manifest.json with Lucid commands (migrations, seeders, make:* commands, truncate/wipe/etc.).
Environment & DB config
.env.example, config/database.ts
Replaces APP_KEY with placeholder; adds PostgreSQL env vars (PG_*), DB_CONNECTION, DB_DEBUG; new config/database.ts configures a pg connection using env values and enables health/debug options.
Model & Migration
app/Models/Task.ts, database/migrations/..._create_tasks_table.ts
Adds Task Lucid model and TaskColor type; adds migration creating tasks table and PostgreSQL task_color enum with idempotent up/down scripts.
Validators
app/Validators/CreateTaskValidator.ts, app/Validators/UpdateTaskValidator.ts
Adds Create/Update validators enforcing title, optional description, enum color, and optional isFavorite with trimming and length constraints.
Controllers
app/Controllers/Http/TasksController.ts, app/Controllers/TasksController.ts
Adds TasksController implementations (Http namespace and legacy path) providing index/show/store/update/destroy with validation, search (q), favorite filtering, and standard HTTP responses.
Routes
start/routes.ts
Removes /vehicles route; adds root health-check and RESTful /tasks routes (GET, POST, PATCH, DELETE).
Dependencies & package
package.json
Pins core/assembler versions; adds @adonisjs/lucid, pg, luxon; updates reflect-metadata and source-map-support versions.
Docs
README.md
Replaces previous README with API-centric README (Portuguese) describing Tasks API, endpoints, migration, and local setup instructions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Routes as start/routes.ts
  participant Controller as TasksController
  participant Validator as Create/Update Validator
  participant Model as Task (Lucid)
  participant DB as PostgreSQL

  Client->>Routes: HTTP GET /tasks?q=&favorite=
  Routes->>Controller: index()
  Controller->>Model: query().if(q).if(favorite).orderBy(created_at)
  Model->>DB: SELECT ...
  DB-->>Model: rows
  Model-->>Controller: Task[]
  Controller-->>Client: 200 JSON

  Client->>Routes: HTTP POST /tasks {title,...}
  Routes->>Controller: store()
  Controller->>Validator: validate(payload)
  Validator-->>Controller: validated data
  Controller->>Model: create(validated)
  Model->>DB: INSERT ...
  DB-->>Model: inserted row
  Model-->>Controller: Task
  Controller-->>Client: 201 JSON

  Client->>Routes: HTTP PATCH /tasks/:id {partial}
  Routes->>Controller: update()
  Controller->>Validator: validate(partial)
  Validator-->>Controller: validated data
  Controller->>Model: findOrFail(id) -> merge + save
  Model->>DB: SELECT/UPDATE
  DB-->>Model: ok
  Controller-->>Client: 200 JSON

  Client->>Routes: HTTP DELETE /tasks/:id
  Routes->>Controller: destroy()
  Controller->>Model: findOrFail(id) -> delete
  Model->>DB: DELETE
  DB-->>Model: ok
  Controller-->>Client: 204
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I nibble wires, ears a-twitch,
New seeds for models — what a switch!
Migrations hop and colors glow,
Lucid rivers start to flow.
Routes and ace — I thump “all set!” 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@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: 15

🧹 Nitpick comments (14)
.env.example (1)

7-15: Sort PG_ keys to satisfy dotenv-linter and reduce churn*

Reorder and keep one key per line without inline comments.

Apply:

-DB_CONNECTION=pg
-PG_HOST=127.0.0.1
-PG_PORT=5432
-PG_USER=corelab
-PG_PASSWORD=corelab
-PG_DB_NAME=corelab
+DB_CONNECTION=pg
+PG_DB_NAME=corelab
+PG_HOST=127.0.0.1
+PG_PASSWORD=corelab
+PG_PORT=5432
+PG_USER=corelab
config/database.ts (1)

7-19: Add connection pool and timeouts to harden DB access

Prevent resource exhaustion and long-hanging queries.

     pg: {
       client: 'pg',
       connection: {
         host: Env.get('PG_HOST', '127.0.0.1') as string,
         port: Number(Env.get('PG_PORT', 5432)),
         user: Env.get('PG_USER', 'postgres') as string,
         password: Env.get('PG_PASSWORD', '') as string,
         database: Env.get('PG_DB_NAME', '') as string,
+        // Optional hardening (supported by node-postgres)
+        connectionTimeoutMillis: 6000,
+        statement_timeout: 8000,
       },
+      pool: { min: 0, max: 10, acquireTimeoutMillis: 10000 },
       migrations: { naturalSort: true },
       healthCheck: true,
       debug: Env.get('DB_DEBUG', 'false') === 'true',
.adonisrc.json (1)

17-21: Remove stale duplicate TasksController.ts
No imports reference App/Controllers/TasksController; delete app/Controllers/TasksController.ts to avoid ambiguity. Optionally verify tests and configurations don’t reference it.

app/Models/Task.ts (1)

15-22: Ensure DB defaults and indexes align with expected filters

  • If isFavorite defaults to false at DB level, declare it in the migration to avoid nulls.
  • If you’ll filter by is_favorite and/or color often, consider indexing accordingly.

Example migration tweak:

this.schema.alterTable('tasks', (table) => {
  table.boolean('is_favorite').notNullable().defaultTo(false).index()
  table.index(['color'])
})
app/Validators/CreateTaskValidator.ts (1)

4-12: Add custom validation messages (DX/i18n).

Return clear, localizable errors instead of defaults.

 export default class CreateTaskValidator {
   constructor(protected ctx: HttpContextContract) {}
 
   public schema = schema.create({
     title: schema.string({}, [rules.trim(), rules.minLength(1), rules.maxLength(120)]),
     description: schema.string.optional({}, [rules.trim(), rules.maxLength(2000)]),
-    color: schema.enum.optional(['yellow', 'blue', 'green', 'peach'] as const),
+    color: schema.enum.optional(TASK_COLORS),
     isFavorite: schema.boolean.optional(),
   })
+
+  public messages = {
+    'title.required': 'title is required',
+    'title.minLength': 'title must have at least 1 character',
+    'title.maxLength': 'title must have at most 120 characters',
+    'description.maxLength': 'description must have at most 2000 characters',
+    'color.enum': 'color must be one of: yellow, blue, green, peach',
+  }
 }
app/Validators/UpdateTaskValidator.ts (1)

4-12: Add custom messages for consistency with Create validator.

 export default class UpdateTaskValidator {
   constructor(protected ctx: HttpContextContract) {}
@@
   public schema = schema.create({
     title: schema.string.optional({}, [rules.trim(), rules.minLength(1), rules.maxLength(120)]),
     description: schema.string.optional({}, [rules.trim(), rules.maxLength(2000)]),
     color: schema.enum.optional(TASK_COLORS),
     isFavorite: schema.boolean.optional(),
   })
+
+  public messages = {
+    'title.minLength': 'title must have at least 1 character',
+    'title.maxLength': 'title must have at most 120 characters',
+    'description.maxLength': 'description must have at most 2000 characters',
+    'color.enum': 'color must be one of: yellow, blue, green, peach',
+  }
 }
database/migrations/0000000000000_create_tasks_table.ts (1)

15-23: Add indexes to support filters.

If the API lists/filter by color/is_favorite/created_at, add indexes.

     this.schema.createTable(this.tableName, (table) => {
       table.increments('id')
       table.string('title', 120).notNullable()
       table.text('description').nullable()
       table.specificType('color', this.enumName).notNullable().defaultTo(this.schema.raw(`'yellow'::${this.enumName}`))
       table.boolean('is_favorite').notNullable().defaultTo(false)
       table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(this.now())
       table.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(this.now())
+      table.index(['color'], 'tasks_color_idx')
+      table.index(['is_favorite'], 'tasks_is_favorite_idx')
+      table.index(['created_at'], 'tasks_created_at_idx')
     })
package.json (1)

5-13: Add DB/migration scripts for DX.

   "scripts": {
     "dev": "node ace serve --watch",
     "build": "node ace build --production",
     "start": "node server.js",
+    "migrate": "node ace migration:run",
+    "migrate:rollback": "node ace migration:rollback",
+    "db:refresh": "node ace migration:refresh",
     "lint": "eslint . --ext=.ts",
     "format": "prettier --write .",
     "test": "node ace test",
     "test:watch": "npm test --watch"
   },
start/routes.ts (2)

3-9: Prefer Route.resource with id constraint.

Cleaner, consistent REST mapping and numeric id guard.

-Route.get('/tasks', 'TasksController.index')
-Route.get('/tasks/:id', 'TasksController.show')
-Route.post('/tasks', 'TasksController.store')
-Route.patch('/tasks/:id', 'TasksController.update')
-Route.delete('/tasks/:id', 'TasksController.destroy')
+Route.resource('tasks', 'TasksController').apiOnly()
+Route.where('id', /^[0-9]+$/)

3-3: Avoid non-ASCII keys in health payload.

JSON key with accent can be awkward for clients; prefer ascii snakeCase/camelCase.

-Route.get('/', async () => ({ Rota_Está_Funcionando: true }))
+Route.get('/', async () => ({ route_is_working: true }))
app/Controllers/Http/TasksController.ts (2)

23-24: Consider pagination to avoid unbounded result sets.

Add simple page/perPage with sane caps.

-    return query.orderBy('created_at', 'desc')
+    const page = Number(request.input('page', 1)) || 1
+    const perPage = Math.min(Number(request.input('perPage', 20)) || 20, 100)
+    return query.orderBy('created_at', 'desc').paginate(page, perPage)

32-38: Leverage Adonis validators instead of manual checks.

Prefer CreateTaskValidator/UpdateTaskValidator for consistent schema and messages.

Add import at top of file:

import CreateTaskValidator from 'App/Validators/CreateTaskValidator'

Then replace request.only + manual checks with:

const payload = await request.validate(CreateTaskValidator)

Similarly in update():

import UpdateTaskValidator from 'App/Validators/UpdateTaskValidator'
const payload = await request.validate(UpdateTaskValidator)
app/Controllers/TasksController.ts (2)

14-17: Trim q before applying filters.

Prevents executing LIKE on whitespace.

-    if (q && q.trim()) {
+    if (q && q.trim()) {
+      const qTrim = q.trim()
-      query.where((b) => b.whereILike('title', `%${q}%`).orWhereILike('description', `%${q}%`))
+      query.where((b) => b.whereILike('title', `%${qTrim}%`).orWhereILike('description', `%${qTrim}%`))
     }

40-42: Standardize error messages (locale and field casing).

Use a consistent language and casing across endpoints, e.g., “title is required”.

-      return response.badRequest({ message: 'title é obrigatório' })
+      return response.badRequest({ error: 'title is required' })
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between b174fe6 and 8310e72.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • .adonisrc.json (2 hunks)
  • .env.example (1 hunks)
  • ace (1 hunks)
  • ace-manifest.json (1 hunks)
  • app/Controllers/Http/TasksController.ts (1 hunks)
  • app/Controllers/TasksController.ts (1 hunks)
  • app/Models/Task.ts (1 hunks)
  • app/Validators/CreateTaskValidator.ts (1 hunks)
  • app/Validators/UpdateTaskValidator.ts (1 hunks)
  • config/database.ts (1 hunks)
  • database/migrations/0000000000000_create_tasks_table.ts (1 hunks)
  • package.json (2 hunks)
  • start/routes.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
app/Controllers/Http/TasksController.ts (2)
app/Controllers/TasksController.ts (1)
  • TasksController (4-75)
app/Models/Task.ts (1)
  • Task (6-29)
app/Controllers/TasksController.ts (2)
app/Controllers/Http/TasksController.ts (1)
  • TasksController (7-84)
app/Models/Task.ts (1)
  • Task (6-29)
🪛 dotenv-linter (3.3.0)
.env.example

[warning] 3-3: [UnorderedKey] The HOST key should go before the PORT key

(UnorderedKey)


[warning] 4-4: [UnorderedKey] The NODE_ENV key should go before the PORT key

(UnorderedKey)


[warning] 5-5: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 5-5: [UnorderedKey] The APP_KEY key should go before the HOST key

(UnorderedKey)


[warning] 5-5: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 12-12: [UnorderedKey] The PG_PASSWORD key should go before the PG_PORT key

(UnorderedKey)


[warning] 13-13: [UnorderedKey] The PG_DB_NAME key should go before the PG_HOST key

(UnorderedKey)

🔇 Additional comments (5)
ace (1)

3-3: Confirm source‑map behavior after switching to register()

Previously install({ handleUncaughtExceptions: false }) avoided double handling; register uses defaults. Please run a failing command (e.g., unknown ace command) and confirm stack traces map to TS and output is clean.

.adonisrc.json (1)

17-18: Restore or remove custom AppProvider registration
The file providers/AppProvider.ts still exists but is no longer listed under "providers" in .adonisrc.json (lines 17–18). Either re-add "./providers/AppProvider" to the providers array or remove the unused file.

app/Models/Task.ts (1)

6-29: Model mapping looks solid and consistent with typical Lucid conventions

Fields, casing, and timestamps are correctly mapped.

app/Validators/UpdateTaskValidator.ts (1)

8-9: Confirm update semantics for empty strings.

title is optional but cannot be ''. With trim + minLength(1), sending "" will 422. Ensure this is intended for PATCH.

ace-manifest.json (1)

98-572: Lucid commands manifest additions look correct.

All expected migration/seeder commands are present; no action needed.

Comment thread .env.example
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=73rHnSEgVPLfFLpTk8omwzBrMk-c75rX
APP_KEY= # preencha com uma chave

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 APP_KEY line: parsing will break and key is missing

Inline comment plus spaces around "=" will be parsed as a value; Adonis will fail to boot if copied as-is. Move the comment to its own line and provide a proper placeholder/generated key.

Apply:

-APP_KEY=   # preencha com uma chave
+# Gere uma chave com: node ace generate:key
+APP_KEY=changeme
📝 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
APP_KEY= # preencha com uma chave
# Gere uma chave com: node ace generate:key
APP_KEY=changeme
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 5-5: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 5-5: [UnorderedKey] The APP_KEY key should go before the HOST key

(UnorderedKey)


[warning] 5-5: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

🤖 Prompt for AI Agents
.env.example around line 5: the APP_KEY line contains an inline comment and
extra spaces which will be parsed as the value and break Adonis boot; change it
to a valid placeholder without spaces around "=", e.g.
APP_KEY=base64:REPLACE_WITH_GENERATED_KEY, and move the explanatory comment to
its own line above (e.g. "# Fill with your app key; generate with `node ace
generate:key`") so parsing and boot succeed.

Comment thread ace
.handle(process.argv.slice(2))
require('source-map-support/register')
const { Ignitor } = require('@adonisjs/core/build/src/Ignitor')
new Ignitor(__dirname).ace().handle(process.argv.slice(2))

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

Handle promise rejection to set a non‑zero exit code on CLI failure

Uncaught rejections may not set exit code consistently. Add a catch and set exit code.

-new Ignitor(__dirname).ace().handle(process.argv.slice(2))
+new Ignitor(__dirname)
+  .ace()
+  .handle(process.argv.slice(2))
+  .catch((err) => {
+    console.error(err)
+    process.exitCode = 1
+  })
📝 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
new Ignitor(__dirname).ace().handle(process.argv.slice(2))
new Ignitor(__dirname)
.ace()
.handle(process.argv.slice(2))
.catch((err) => {
console.error(err)
process.exitCode = 1
})
🤖 Prompt for AI Agents
In ace around line 5, the promise returned by new
Ignitor(__dirname).ace().handle(process.argv.slice(2)) is not handled for
rejections; update the call to attach a catch handler that logs the error (or
sends it to your logger) and sets a non-zero exit code (e.g., process.exitCode =
1 or process.exit(1)) so CLI failures result in a failing process; keep the rest
of the call chain intact.

Comment on lines +4 to +6
const ALLOWED_COLORS = ['yellow', 'blue', 'green', 'peach'] as const
type AllowedColor = typeof ALLOWED_COLORS[number]

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

Add a robust boolean parser to prevent Boolean('false') bugs.

Introduce a helper and reuse it across index/store/update.

 const ALLOWED_COLORS = ['yellow', 'blue', 'green', 'peach'] as const
 type AllowedColor = typeof ALLOWED_COLORS[number]
 
+function parseBoolean(v: unknown): boolean | undefined {
+  if (v === undefined || v === null) return undefined
+  if (typeof v === 'boolean') return v
+  const s = String(v).trim().toLowerCase()
+  if (['true', '1', 'yes', 'y'].includes(s)) return true
+  if (['false', '0', 'no', 'n'].includes(s)) return false
+  return undefined
+}
📝 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
const ALLOWED_COLORS = ['yellow', 'blue', 'green', 'peach'] as const
type AllowedColor = typeof ALLOWED_COLORS[number]
const ALLOWED_COLORS = ['yellow', 'blue', 'green', 'peach'] as const
type AllowedColor = typeof ALLOWED_COLORS[number]
function parseBoolean(v: unknown): boolean | undefined {
if (v === undefined || v === null) return undefined
if (typeof v === 'boolean') return v
const s = String(v).trim().toLowerCase()
if (['true', '1', 'yes', 'y'].includes(s)) return true
if (['false', '0', 'no', 'n'].includes(s)) return false
return undefined
}
🤖 Prompt for AI Agents
In app/Controllers/Http/TasksController.ts around lines 4–6, add a robust
boolean parser helper (e.g., parseBoolean(value): boolean) that treats
true/1/"true"/"1"/true as true and false/0/"false"/"0"/null/undefined/"" as
false to avoid JavaScript's Boolean('false') pitfall, export or place it at top
of the file, then replace any direct Boolean(...) or truthy checks in index,
store and update handlers with parseBoolean for incoming params (query/body)
that represent boolean flags (e.g., completed, archived), and update
imports/type annotations as needed so all three methods reuse the new helper.

Comment on lines +9 to +11
const q = request.input('q') as string | undefined
const favorite = request.input('favorite')

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

Harden query parsing: trim q and correctly parse favorite.

Avoid false positives/negatives on booleans and ignore empty q.

-    const q = request.input('q') as string | undefined
-    const favorite = request.input('favorite')
+    const qRaw = request.input('q')
+    const q = typeof qRaw === 'string' ? qRaw.trim() : undefined
+    const favParam = request.input('favorite')
@@
-    if (q && q.trim()) {
+    if (q) {
       query.where((b) => b.whereILike('title', `%${q}%`).orWhereILike('description', `%${q}%`))
     }
@@
-    if (favorite !== undefined) {
-      const fav = String(favorite).toLowerCase() === 'true'
-      query.where('is_favorite', fav)
-    }
+    const fav = parseBoolean(favParam)
+    if (fav !== undefined) {
+      query.where('is_favorite', fav)
+    }

Also applies to: 14-16, 18-21

🤖 Prompt for AI Agents
In app/Controllers/Http/TasksController.ts around lines 9-11 (and similarly
update 14-16, 18-21), trim and normalize the 'q' input and robustly parse the
'favorite' input: read raw values (const qRaw = request.input('q')), set q =
typeof qRaw === 'string' ? qRaw.trim() || undefined : undefined to ignore empty
queries, and parse favorite by inspecting the raw type (if boolean use as-is; if
string normalize to lower-case and map 'true','1','yes' => true and
'false','0','no' => false; if number treat 1 as true and 0 as false; otherwise
undefined). Replace direct casts with this normalization so downstream logic
sees either undefined, a trimmed non-empty q, or a boolean favorite.

Comment on lines +40 to +43
if (!title || !String(title).trim()) return response.badRequest({ error: 'title is required' })
if (!ALLOWED_COLORS.includes(color as AllowedColor)) {
return response.badRequest({ error: `color must be one of ${ALLOWED_COLORS.join(', ')}` })
}

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

Color is unintentionally required; default to 'yellow' when omitted and then validate.

Prevents unnecessary 400s when color isn’t sent.

-    if (!title || !String(title).trim()) return response.badRequest({ error: 'title is required' })
-    if (!ALLOWED_COLORS.includes(color as AllowedColor)) {
+    if (!title || !String(title).trim()) return response.badRequest({ error: 'title is required' })
+    const normalizedColor = (color ?? 'yellow') as AllowedColor
+    if (!ALLOWED_COLORS.includes(normalizedColor)) {
       return response.badRequest({ error: `color must be one of ${ALLOWED_COLORS.join(', ')}` })
     }
@@
       title: String(title).trim(),
       description: description ?? null,
-      color: color as AllowedColor,
-      isFavorite: Boolean(isFavorite),
+      color: normalizedColor,
+      isFavorite: parseBoolean(isFavorite) ?? false,
     })

Also applies to: 45-50

🤖 Prompt for AI Agents
In app/Controllers/Http/TasksController.ts around lines 40-43 (and also apply
the same change to lines 45-50), the controller currently rejects requests when
color is missing; instead, if color is undefined or empty, default it to
'yellow' before validation, then validate that the resulting value is in
ALLOWED_COLORS and return a 400 only if the final value is invalid; implement
this by assigning color = color ?? 'yellow' (or similar) prior to the
ALLOWED_COLORS.includes check for both create and update flows so missing color
no longer causes a 400.

Comment thread config/database.ts
},
migrations: { naturalSort: true },
healthCheck: true,
debug: (Env.get('DB_DEBUG', false) as boolean) || false,

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

DB_DEBUG is coerced incorrectly; likely always truthy when set

Env.get returns strings unless validated; casting to boolean doesn't convert at runtime. "false" is truthy.

Apply:

-      debug: (Env.get('DB_DEBUG', false) as boolean) || false,
+      // Accept "true"/"false" strings without relying on env.ts coercion
+      debug: Env.get('DB_DEBUG', 'false') === 'true',
📝 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
debug: (Env.get('DB_DEBUG', false) as boolean) || false,
// Accept "true"/"false" strings without relying on env.ts coercion
debug: Env.get('DB_DEBUG', 'false') === 'true',
🤖 Prompt for AI Agents
In config/database.ts around line 18, the debug flag is set by casting
Env.get(...) to boolean which doesn't convert string values (so "false" is
truthy); change the assignment to parse the string properly (for example use
Env.get('DB_DEBUG', 'false') === 'true' or implement a small helper that accepts
'true'/'1'/'yes' as true and defaults to false) so debug ends up a real boolean
with a safe default.

Comment on lines +8 to +13
this.schema.raw(`DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
CREATE TYPE ${this.enumName} AS ENUM ('yellow', 'blue', 'green', 'peach');
END IF;
END$$;`)

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

Be explicit about PL/pgSQL language in DO blocks.

Some PG setups require LANGUAGE; add it to avoid failures.

-    END$$;`)
+    END$$ LANGUAGE plpgsql;`)

Apply the same to the down() DO block.

📝 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
this.schema.raw(`DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
CREATE TYPE ${this.enumName} AS ENUM ('yellow', 'blue', 'green', 'peach');
END IF;
END$$;`)
this.schema.raw(`DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
CREATE TYPE ${this.enumName} AS ENUM ('yellow', 'blue', 'green', 'peach');
END IF;
END$$ LANGUAGE plpgsql;`)
🤖 Prompt for AI Agents
In database/migrations/0000000000000_create_tasks_table.ts around lines 8 to 13,
the DO $$ ... $$ blocks are missing an explicit LANGUAGE declaration which can
cause failures on some PostgreSQL setups; update both the up() and down() DO
blocks to append "LANGUAGE plpgsql;" after the closing $$ (i.e. DO $$ ... $$
LANGUAGE plpgsql;) so the block is explicitly executed as PL/pgSQL and ensure
the same change is applied to the down() block that drops or alters the enum.

Comment on lines +19 to +22
table.specificType('color', this.enumName).notNullable().defaultTo('yellow')
table.boolean('is_favorite').notNullable().defaultTo(false)
table.timestamp('created_at', { useTz: true }).notNullable()
table.timestamp('updated_at', { useTz: true }).notNullable()

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

Defaults: cast enum and timestamp defaults.

  • Default enum literal should be cast to the enum type to avoid “type mismatch” in some PG versions.
  • created_at/updated_at are NOT NULL but lack defaults; add now() to avoid insert errors outside Lucid.
-      table.specificType('color', this.enumName).notNullable().defaultTo('yellow')
+      table.specificType('color', this.enumName).notNullable().defaultTo(this.schema.raw(`'yellow'::${this.enumName}`))
-      table.boolean('is_favorite').notNullable().defaultTo(false)
-      table.timestamp('created_at', { useTz: true }).notNullable()
-      table.timestamp('updated_at', { useTz: true }).notNullable()
+      table.boolean('is_favorite').notNullable().defaultTo(false)
+      table.timestamp('created_at', { useTz: true }).notNullable().defaultTo(this.now())
+      table.timestamp('updated_at', { useTz: true }).notNullable().defaultTo(this.now())
📝 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
table.specificType('color', this.enumName).notNullable().defaultTo('yellow')
table.boolean('is_favorite').notNullable().defaultTo(false)
table.timestamp('created_at', { useTz: true }).notNullable()
table.timestamp('updated_at', { useTz: true }).notNullable()
table.specificType('color', this.enumName)
.notNullable()
.defaultTo(this.schema.raw(`'yellow'::${this.enumName}`))
table.boolean('is_favorite')
.notNullable()
.defaultTo(false)
table.timestamp('created_at', { useTz: true })
.notNullable()
.defaultTo(this.now())
table.timestamp('updated_at', { useTz: true })
.notNullable()
.defaultTo(this.now())
🤖 Prompt for AI Agents
In database/migrations/0000000000000_create_tasks_table.ts around lines 19 to
22, the enum default should be explicitly cast to the enum type and the
created_at/updated_at timestamps need defaults to avoid NOT NULL insertion
errors; update the color default to use a casted enum literal (e.g. use a
raw/default expression that casts 'yellow' to the enum type) and set created_at
and updated_at to default to now() (while keeping notNullable).

Comment on lines +28 to +33
this.schema.raw(`DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
DROP TYPE ${this.enumName};
END IF;
END$$;`)

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

Same fix for down() DO block.

-    END$$;`)
+    END$$ LANGUAGE plpgsql;`)
📝 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
this.schema.raw(`DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
DROP TYPE ${this.enumName};
END IF;
END$$;`)
this.schema.raw(`DO $$
BEGIN
IF EXISTS (SELECT 1 FROM pg_type WHERE typname = '${this.enumName}') THEN
DROP TYPE ${this.enumName};
END IF;
END$$ LANGUAGE plpgsql;`)
🤖 Prompt for AI Agents
In database/migrations/0000000000000_create_tasks_table.ts around lines 28 to
33, the down() migration still lacks the safe DO $$ block used in up() that
checks for the enum type's existence before dropping it; update the down()
method to run the same DO $$ BEGIN IF EXISTS (SELECT 1 FROM pg_type WHERE
typname = 'this.enumName') THEN DROP TYPE this.enumName; END IF; END $$; pattern
(using the same this.enumName interpolation/variable) so the enum is only
dropped if it exists and matches the fix applied in up().

Comment thread package.json
Comment on lines +57 to 65
"@adonisjs/core": "5.9.0",
"@adonisjs/lucid": "18.4.2",
"@adonisjs/repl": "^3.1.10",
"luxon": "3.7.1",
"pg": "8.16.3",
"proxy-addr": "^2.0.7",
"reflect-metadata": "^0.1.13",
"source-map-support": "^0.5.21"
"reflect-metadata": "0.1.14",
"source-map-support": "0.5.21"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Check Node engine compatibility with pinned Adonis/Lucid versions.

Pinned deps are strict; ensure Node 16.15.x satisfies all engine ranges.


🏁 Script executed:

#!/bin/bash
# Validate engines and peer deps
node -v
npm -v
# Dry-run install to surface engine/version conflicts
npm i --package-lock-only --ignore-scripts
# Show resolved versions
npm ls @adonisjs/core @adonisjs/lucid pg luxon

Length of output: 785


Fix Node.js engine version mismatch in package.json. The current engines.node range ^16.15.0 triggers EBADENGINE warnings on Node v24.3.0; either lock dev/CI to Node 16.15.x or broaden the range (e.g. >=16 <25) to cover your target versions.

🤖 Prompt for AI Agents
In package.json around lines 57 to 65 the current engines.node range (^16.15.0)
causes EBADENGINE warnings on Node 24.3.0; update the engines.node field to
either lock CI/dev to Node 16.15.x (e.g., exact 16.15.0 in toolchains) or
broaden the semver range to cover your target runtime (for example ">=16 <25")
so Node 24 is accepted, then run npm install/ci to verify no engine warnings
remain.

@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: 3

🧹 Nitpick comments (5)
README.md (5)

17-17: Corrigir termo: “autoincremento”

Em PT-BR, recomenda-se “autoincremento” (uma palavra), não “auto-increment”.

Aplicar:

- - `id` (PK, auto-increment)
+ - `id` (PK, autoincremento)

71-74: Ajuste de gramática em pré-requisitos

Trocar “um database criado” por “um banco de dados criado”.

- - **PostgreSQL** rodando e com um database criado
+ - **PostgreSQL** em execução e com um banco de dados criado

46-66: Especificar linguagem no bloco de código da estrutura

Falta a linguagem no fenced code (MD040). Use “text” para evitar lint warnings.

-```
+```text
 app/
   Controllers/
     Http/
       TasksController.ts
   Models/
     Task.ts
 ...
-```
+```

154-166: Documentar paginação e ordenação da listagem

A rota aceita filtros; faltam paginação (page/perPage) e ordem padrão. Adicione agora ao README, mesmo que simples, para guiar consumo.

 **Query params:**
 - `q` — busca parcial em `title` e `description`
-- `favorite` — `true` | `false`
+- `favorite` — `true` | `false`
+- `page` — página (padrão `1`)
+- `perPage` — itens por página (padrão `10`)
+- `orderBy` — campo de ordenação (padrão `created_at`)
+- `order` — `asc` | `desc` (padrão `desc`)
 
 **Exemplos:**
 ```bash
 curl -s http://127.0.0.1:3333/tasks | jq .
-curl -s "http://127.0.0.1:3333/tasks?q=Adonis&favorite=true" | jq .
+curl -s "http://127.0.0.1:3333/tasks?q=Adonis&favorite=true&page=1&perPage=10&orderBy=created_at&order=desc" | jq .

---

`195-202`: **Clarificar “correções conhecidas” e versões Lucid/Decorators**

A nota sobre `@column.dateTime()` é útil; recomendo apontar versão mínima do Lucid que exige isso para evitar confusão.

```diff
-  - Decorators de data → usar `@column.dateTime()` (Lucid 18) no lugar do legado `DateTimeColumn`.
+  - Decorators de data → usar `@column.dateTime()` (Lucid ≥18) no lugar do legado `DateTimeColumn`.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8310e72 and eafb93c.

📒 Files selected for processing (1)
  • README.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[misspelling] ~17-~17: Esta é uma palavra só.
Context: ... Domínio Task Campos: - id (PK, auto-increment) - title (string, obrigatório) - `des...

(AUTO)


[grammar] ~73-~73: Possível erro de concordância.
Context: ...essário) - PostgreSQL rodando e com um database criado Selecionar Node 16: ```bash...

(GENERAL_GENDER_AGREEMENT_ERRORS)


[style] ~197-~197: Se for linguagem de Internet, considere escrever “que” por extenso. Se quis dizer “q”, coloque entre aspas.
Context: ...egura de color. - Busca simples via q em title/description e **filtro ...

(INTERNET_ABBREVIATIONS)

🪛 markdownlint-cli2 (0.17.2)
README.md

46-46: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (2)
README.md (2)

24-27: Nota sobre reversão de enum Postgres na migration (down)

Ao remover, é preciso dropar a tabela que usa o tipo e só então o enum (DROP TYPE task_color). Documente esse detalhe para evitar falhas em rollback.

 - Cria **tipo enum nativo** no Postgres (`task_color`)
 - Cria tabela `tasks` com as colunas acima
+  - Observação: no `down()`, remova a tabela antes e depois o tipo:
+    1) `DROP TABLE tasks`
+    2) `DROP TYPE task_color`

139-145: Documentar naming de isFavorite vs favorite no README.md
O modelo mapeia is_favoriteisFavorite e os controllers filtram por query param favorite. Atualize a seção de query params (linhas 139–145):

- `favorite` — `true` | `false`
+ `favorite` — `true` | `false` (filtro via query string)

Adicione logo abaixo:

O payload JSON envia isFavorite, o filtro por query usa favorite, e no banco o campo é is_favorite (mapeado em app/Models/Task.ts via @column({ columnName: 'is_favorite', serializeAs: 'isFavorite' })).

Exemplo de uso:

curl -s "http://127.0.0.1:3333/tasks?q=Adonis&favorite=true" | jq .

Código não requer alterações.

Comment thread README.md
Comment on lines +72 to +79
- **Node 16.x** (use `nvm` se necessário)
- **PostgreSQL** rodando e com um database criado

**Selecionar Node 16:**
```bash
nvm install 16
nvm use 16
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Node 16 está EOL — verificar suporte para LTS atual (18/20) e engines

Confirme compatibilidade do projeto e do Adonis v5 com Node LTS atual e ajuste README e package.json (“engines”) se aplicável.

Also applies to: 198-199


🏁 Script executed:

#!/bin/bash
set -e
echo "Engines em package.json:"
jq -r '.engines // {}' package.json 2>/dev/null || echo "package.json não encontrado"

echo -e "\nDependências Adonis/Lucid:"
jq -r '.dependencies, .devDependencies' package.json 2>/dev/null | rg -nP 'adonis|@adonisjs|lucid' || true

echo -e "\nVerifique também no CHANGELOG do AdonisJS v5 suporte a Node 18/20."

Length of output: 703


Atualizar Node.js em README e engines para LTS atual
Node 16 está EOL desde abril 30, 2024 (eol.support); Adonis v5 requer Node ≥ 14.15.4 (v5-docs.adonisjs.com), então atualize package.json.engines.node para algo como ^20.0.0 (ou >=18.0.0) e ajuste o README para usar nvm install 20 / nvm use 20.

🧰 Tools
🪛 LanguageTool

[grammar] ~73-~73: Possível erro de concordância.
Context: ...essário) - PostgreSQL rodando e com um database criado Selecionar Node 16: ```bash...

(GENERAL_GENDER_AGREEMENT_ERRORS)

🤖 Prompt for AI Agents
In README.md around lines 72 to 79, the docs still reference Node 16 which is
EOL; update the README instructions and any nvm commands to recommend the
current LTS (e.g., Node 20) and change examples from `nvm install 16` / `nvm use
16` to `nvm install 20` / `nvm use 20`; additionally update
package.json.engines.node to require a modern LTS (for example set to `^20.0.0`
or a minimum of `>=18.0.0`) so the project enforces the supported Node version.

Comment thread README.md
Comment on lines +86 to +104
**Configurar `.env`:**
```dotenv
# App
PORT=3333
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=alguma-chave-secreta

# Banco
DB_CONNECTION=pg
PG_HOST=127.0.0.1
PG_PORT=5432
PG_USER=corelab
PG_PASSWORD=corelab
PG_DB_NAME=corelab

# Necessário para o validador de env do Adonis
DRIVE_DISK=local
```

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

Gerar APP_KEY em vez de placeholder no .env

APP_KEY deve ser gerado via Ace. Inclua instrução explícita.

 APP_KEY=alguma-chave-secreta
+
+# Gere uma chave válida:
+#   node ace generate:key
+# Copie o valor gerado para APP_KEY
📝 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
**Configurar `.env`:**
```dotenv
# App
PORT=3333
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=alguma-chave-secreta
# Banco
DB_CONNECTION=pg
PG_HOST=127.0.0.1
PG_PORT=5432
PG_USER=corelab
PG_PASSWORD=corelab
PG_DB_NAME=corelab
# Necessário para o validador de env do Adonis
DRIVE_DISK=local
```
**Configurar `.env`:**
🤖 Prompt for AI Agents
In README.md around lines 86 to 104, the .env snippet uses a placeholder APP_KEY
value; update the instructions to tell users to generate a real key via Ace
(e.g., run the Adonis command to generate an app key) and paste it into the
APP_KEY field instead of using a static placeholder; include the exact Ace
command to run and a short note to keep the key secret.

Comment thread README.md
Comment on lines +129 to +131
```json
{ Rota_Está_Funcionando: true }
```

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

Exemplo de resposta inválido (JSON malformado)

Chave sem aspas invalidará o JSON. Sugiro chave simples e válida.

-```json
-{ Rota_Está_Funcionando: true }
-```
+```json
+{ "ok": true }
+```
🤖 Prompt for AI Agents
In README.md around lines 129 to 131 the example JSON block is malformed because
the key lacks quotes and the fenced block markers are inconsistent; replace the
invalid example with a valid JSON object and proper fenced code block markers —
e.g. use a triple-backtick JSON fence and the object {"ok": true} as the content
so the snippet is syntactically valid JSON.

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