Skip to content

feat(categories): add categories create to complete the v1 surface#21

Merged
dgilperez merged 2 commits into
mainfrom
feat/cli-categories-create
May 23, 2026
Merged

feat(categories): add categories create to complete the v1 surface#21
dgilperez merged 2 commits into
mainfrom
feat/cli-categories-create

Conversation

@dgilperez
Copy link
Copy Markdown
Collaborator

Last-mile patch for #11: wraps POST /api/v1/categories, the only remaining /api/v1 write endpoint that wasn't exposed in the CLI.

Command

sure-cli categories create --name Food --color '#3b82f6'                           # dry-run
sure-cli categories create --name Food --color '#3b82f6' --apply                   # execute
sure-cli categories create --name Subscriptions --color '#10b981' \
  --icon wallet --parent-id <parent_id> --apply

Validation (mirrors upstream Category model)

Flag Required? Client-side check Server-side check
--name yes non-whitespace presence validates :name, presence: true, uniqueness: { scope: :family_id }
--color yes matches ^#[0-9A-Fa-f]{6}$ (same regex as the model) format: { with: /\A#[0-9A-Fa-f]{6}\z/ }
--icon no propagated as-is upstream category_params maps :icon:lucide_icon; Category.suggested_icon(name) runs if blank
--parent-id no propagated as-is upstream verifies the parent belongs to the family, 422s otherwise

Body is wrapped as {"category": {...}} to match params.require(:category).

Tests (TDD)

8 unit tests:

  • RequiresName, RequiresColor, WhitespaceOnlyNameRejected
  • ColorMustBeHex — rejects 3b82f6, blue, #abc, #GGGGGG, #3b82f6 (trailing space)
  • AcceptsValidHex — accepts #3b82f6, #000000, #FFFFFF, #abcdef
  • WrapsInCategoryKey — top-level category key + optional-field omission
  • OptionalFields — icon + parent_id propagate
  • TestCategoriesCreateRegistered — full flag set + resolved-name check

go test ./... green across the suite.

Coverage note

After this lands, the CLI mirrors every /api/v1 endpoint that is meaningfully usable from a shell. The remaining auth endpoints (signup, sso_*) are intentionally not wrapped — they are mobile-device-bound flows (require device_id, device_name, device_type, os_version, app_version) that don't fit a CLI use case.

Refs #11.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

Warning

Review limit reached

@dgilperez, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 50 minutes and 7 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 198309d2-7c07-4c68-b129-aabb678b7670

📥 Commits

Reviewing files that changed from the base of the PR and between a9210fe and 424e29c.

📒 Files selected for processing (4)
  • README.md
  • cmd/sure-cli/root/categories_create_test.go
  • cmd/sure-cli/root/reference_cmds.go
  • docs/ROADMAP.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cli-categories-create

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.

@superagent-security superagent-security Bot added contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis. labels May 23, 2026
dgilperez added 2 commits May 23, 2026 21:38
Closes the last `/api/v1` write endpoint that was unexposed in the CLI:
`POST /api/v1/categories` (Api::V1::CategoriesController#create).

Body matches the upstream `params.require(:category).permit(:name,
:color, :icon, :parent_id)` shape (icon is mapped to lucide_icon
server-side, so we keep the original key).

Client-side validation matches the Category model:

- `--name` required (server-side: presence + uniqueness per family).
- `--color` required and validated against `^#[0-9A-Fa-f]{6}$` — same
  regex the model uses — so users get fast feedback before a 422.
- `--icon` optional; upstream auto-suggests via
  `Category.suggested_icon(name)` when blank.
- `--parent-id` optional; upstream verifies it belongs to the family
  and 422s otherwise.

8 unit tests cover: missing name, missing color, invalid hex formats
(short, non-hex, trailing space), accepted hex formats, payload wraps
in `{category: ...}`, optional fields propagate, whitespace-only name
rejected, and command registration with the full flag set.

After this lands the CLI mirrors every `/api/v1` endpoint that is
meaningfully usable from a shell. The remaining auth endpoints
(`signup`, `sso_*`) are intentionally not wrapped — they are
mobile-device-bound flows that don't fit a CLI.

Refs #11.
buildCategoryCreatePayload trimmed whitespace before the presence check
but then sent the original `o.Name` in the payload. With
`--name '  Food  '` that meant the request body included the spaces
even though validation looked at the trimmed value — which would clash
with the upstream uniqueness check against an existing 'Food'.

Send the trimmed value to match validation. Adds regression test
TestBuildCategoryCreatePayload_TrimsNameInPayload.
@dgilperez dgilperez force-pushed the feat/cli-categories-create branch from af0f664 to 424e29c Compare May 23, 2026 19:38
@dgilperez dgilperez merged commit 90ee7c0 into main May 23, 2026
5 checks passed
@dgilperez dgilperez deleted the feat/cli-categories-create branch May 23, 2026 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor:verified Contributor passed trust analysis. pr:verified PR passed security analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant