Skip to content

ref(commands): add listCommand factory and migrate all list commands - #270

Closed
BYK wants to merge 6 commits into
mainfrom
ref/list-command-abstraction
Closed

ref(commands): add listCommand factory and migrate all list commands#270
BYK wants to merge 6 commits into
mainfrom
ref/list-command-abstraction

Conversation

@BYK

@BYK BYK commented Feb 23, 2026

Copy link
Copy Markdown
Member

Summary

Introduces a shared listCommand factory in src/lib/list-helpers.ts that eliminates ~800 lines of duplicated boilerplate across the 7 sentry * list commands.

What changed

New factory (src/lib/list-helpers.ts)

  • listCommand<T>() — wraps buildCommand with shared flags (--limit, --json, optional --query, --sort, --cursor, --follow), the full output pipeline (JSON → empty state → render → truncation → footer tip), and cursor cache management
  • Supporting helpers: fetchFromOrgs, resolveOrgsForList, resolveSingleTarget, makeValidateLimit, resolveCursorFlag, updateCursorCache

Migrated commands — each now a thin config object; all boilerplate removed:

  • org/list, team/list, repo/list, trace/list, log/list, issue/list
  • project/list — partially improved (parallel fetch via fetchFromOrgs, shared org resolution)

Cursor pagination added to team/list and repo/list (--cursor/-c last)

API client fixes (src/lib/api-client.ts):

  • listTeams / listRepositories rewritten via orgScopedPaginateAll — fixes silent truncation at 100 items
  • listIssues rewritten to bypass @sentry/api SDK which discards Link response headers
  • New paginated single-page variants: listTeamsPaginated, listRepositoriesPaginated, listIssuesPaginated

Other fixes:

  • trace/list was incorrectly importing from @stricli/core directly, bypassing the telemetry wrapper — fixed
  • Sequential fetchAll* loops in project/list replaced with parallel Promise.all via fetchFromOrgs

BYK added 6 commits February 18, 2026 11:00
… errors

When the @sentry/api SDK returns a non-2xx response, the error object is
the parsed JSON body (e.g. { detail: "Not found" }). The throwApiError
function was using String(error) as fallback, which produces the
unhelpful "[object Object]" for any plain object.

Introduce stringifyUnknown() in errors.ts as a central utility that
safely converts unknown values to readable strings: strings pass through,
Error instances yield .message, objects are JSON-serialized, and
primitives use String(). Replace all 8 call sites across the codebase
that had the same String(error) / ternary pattern with this utility.

Closes #256
Wrap JSON.stringify in try/catch to gracefully handle circular
references and BigInt values. Falls back to String() which is
always safe. Add tests for both edge cases.

Addresses Cursor BugBot feedback on PR #259.
…e/log list commands

Introduces src/lib/list-helpers.ts with:
- listCommand() factory wrapping buildCommand with standard flags (--limit,
  --json, optional --query/--sort/--cursor/--follow), output pipeline, and
  cursor cache management
- fetchFromOrgs() — parallel multi-org fetch with graceful per-org error handling
- resolveOrgsForList() — org resolution chain (explicit → default → DSN auto-detect)
- resolveSingleTarget() — single org+project resolution for trace/log commands
- makeValidateLimit() — range-checked limit parser factory
- writeSelfHostedWarning(), resolveCursorFlag(), updateCursorCache() helpers

Migrated 5 list commands to use the factory:
- org/list.ts: ~120 → ~104 lines
- team/list.ts: ~270 → ~127 lines (eliminates fetchOrgTeamsSafe + resolveOrgsToFetch duplicates)
- repo/list.ts: ~270 → ~130 lines (eliminates fetchOrgRepositoriesSafe + resolveOrgsToFetch duplicates)
- trace/list.ts: ~230 → ~126 lines (also fixes @stricli/core import → lib/command.js)
- log/list.ts: ~360 → ~238 lines (keeps streaming loop, uses factory for non-follow path)

All 1723 unit tests pass.
…d helpers

- Replace fetchAllOrgProjects sequential for-loop with fetchFromOrgs() (parallel)
- Replace resolveOrgsForAutoDetect (120 lines) with thin wrapper around resolveOrgsForList
- Remove now-unused imports: listOrganizations, getDefaultOrganization, resolveAllTargets
…ssues via raw requests

- team/list: add --cursor/-c flag using listTeamsPaginated for single-org fetches
- repo/list: add --cursor/-c flag using listRepositoriesPaginated for single-org fetches
- api-client: rewrite listTeams/listRepositories to use orgScopedPaginateAll (fixes silent truncation)
- api-client: add listTeamsPaginated, listRepositoriesPaginated, listIssuesPaginated helpers
- api-client: rewrite listIssues to bypass @sentry/api SDK, enabling access to Link header
Eliminates ~150 lines of boilerplate by using the shared listCommand factory.
All resolution, alias, sorting, and fetch logic stays in the fetch callback.
JSON output uses formatJson override; footer tip uses function form to pick
the right tip text based on single vs multi-project mode.
@github-actions

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Build

  • Add hole-punch tool to reduce compressed binary size by BYK in #245
  • Add gzip-compressed binary downloads by BYK in #244

Other

  • (args) Parse Sentry web URLs as CLI arguments by BYK in #252
  • (auth) Switch to /auth/ endpoint and add whoami command by BYK in #266
  • (list) Add pagination and consistent target parsing to all list commands by BYK in #262

Bug Fixes 🐛

Telemetry

  • Reduce noise from version-check JSON parse errors by BYK in #253
  • Skip Sentry reporting for 4xx API errors by BYK in #251
  • Handle EPIPE errors from piped stdout gracefully by BYK in #250
  • Upgrade Sentry SDK to 10.39.0 and remove custom patches by BYK in #249

Other

  • (commands) Support org/project/id as single positional arg by BYK in #261
  • (db) Handle readonly database gracefully instead of crashing by betegon in #235
  • (errors) Show meaningful detail instead of [object Object] in API errors by BYK in #259
  • (issue-list) Propagate original errors instead of wrapping in plain Error by BYK in #254
  • (npm) Add Node.js >= 22 version guard to npm bundle by BYK in #269
  • (polyfill) Add exited promise and stdin to Bun.spawn Node.js polyfill by BYK in #248
  • (project-list) Add pagination and flexible target parsing by BYK in #221
  • (test) Prevent mock.module() leak from breaking test:isolated by BYK in #260
  • (upgrade) Remove v prefix from release URLs and work around Bun.write streaming bug by BYK in #243
  • Repair pagination_cursors composite PK and isolate test suites by BYK in #265

Internal Changes 🔧

  • (build) Replace local hole-punch script with binpunch package by BYK in #246
  • (commands) Add listCommand factory and migrate all list commands by BYK in #270
  • Use @sentry/api client for requests by MathurAditya724 in #226

Other


🤖 This preview updates automatically when you update the PR.

@BYK

BYK commented Feb 23, 2026

Copy link
Copy Markdown
Member Author

Closing in favour of a rebased version — PR #262 landed a very similar refactor on main (dispatchOrgScopedList + buildOrgListCommand). Will open a fresh PR from main that only adds what's new: migrating org/list to the existing buildOrgListCommand factory.

@BYK BYK closed this Feb 23, 2026
@BYK
BYK deleted the ref/list-command-abstraction branch March 20, 2026 19:40
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