feat(list): add pagination and consistent target parsing to all list commands - #262
Merged
Conversation
Bun's mock.module() leaks across test files in the same run. The simplified stub for formatMultipleProjectsFooter in the dsn/index.js mock was poisoning errors.test.ts, causing 4 failures in test:isolated. Import the real function from its source file (dsn/errors.js) and pass it through the mock so the leaked version retains real behavior. Fixes #258
Contributor
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨Build
Other
Bug Fixes 🐛Telemetry
Other
Internal Changes 🔧
🤖 This preview updates automatically when you update the PR. |
Contributor
Codecov Results 📊✅ Patch coverage is 88.46%. Project has 3644 uncovered lines. Files with missing lines (69)
Coverage diff@@ Coverage Diff @@
## main #PR +/-##
==========================================
+ Coverage 73.15% 73.98% +0.83%
==========================================
Files 111 114 +3
Lines 13756 14005 +249
Branches 0 0 —
==========================================
+ Hits 10063 10361 +298
- Misses 3693 3644 -49
- Partials 0 0 —Generated by Codecov Action |
- Rewrite team/list and repo/list tests with 23 tests each covering explicit, auto-detect, org-all, cursor, ValidationError, and ContextError modes - Add org-all cursor pagination tests to issue/list - Add new resolve-target-listing.test.ts with 19 tests for resolveOrgsForListing, resolveOrgProjectTarget, and resolveOrgProjectFromArg - Fix api-client.test.ts: close missing listTeamsPaginated describe block, add cursor/perPage tests for listTeamsPaginated, fix Link header format to use named cursor attribute instead of URL query param
- Fix malformed 'project:' filter: empty projectSlug now produces empty string (falsy) so .filter(Boolean) correctly removes it for org-wide listing - Fix isMultiProject=false in org-all issue listing: set to true so the ALIAS column shows which project each issue belongs to - Fix missing hasMore check on empty page in issue list org-all path: show 'try the next page' hint instead of definitive 'no issues' when hasMore=true - Remove redundant footer tip from handleOrgAll in repo/list and team/list: the tip told users to do what they already did - Deduplicate buildContextKey/resolveCursor: extract buildOrgContextKey and resolveOrgCursor into src/lib/db/pagination.ts and update all callers
…repo commands Introduce OrgListConfig-driven dispatch and a generic table renderer to eliminate ~670 lines of duplicated code between team/list and repo/list. New modules: - src/lib/org-list.ts: fetchOrgSafe, fetchAllOrgs, handleOrgAll, handleAutoDetect, handleExplicitOrg, dispatchOrgScopedList - src/lib/formatters/table.ts: writeTable with Column<T> definitions team/list.ts: 420 → 127 lines (-70%) repo/list.ts: 424 → 125 lines (-71%)
Add LIST_TARGET_POSITIONAL, LIST_JSON_FLAG, LIST_CURSOR_FLAG, buildListLimitFlag, and LIST_BASE_ALIASES as shared constants so all four list commands stop redefining the same flag/positional shapes. Add buildOrgListCommand factory (Level B) for team and repo commands whose entire func body is dispatchOrgScopedList; reduces those files to config + column definitions + one call. team/list.ts and repo/list.ts each drop ~40 more lines. project/list.ts and issue/list.ts spread the shared constants, removing the duplicated positional/json/cursor/limit definitions. 12 new tests in test/lib/list-command.test.ts; 1850 unit tests pass.
…e-slug routing - team list: add listForProject (project-scoped teams via listAProject_sTeams) - repo list: bare slug now routes through project-search → org-scoped fallback - project list and issue list: replace switch-case dispatch with dispatchOrgScopedList + overrides - team/repo list tests: update to mock findProjectsBySlug for project-search mode - org-list.ts: full rewrite with ListCommandMeta, OrgListConfig, ModeHandlerMap, dispatchOrgScopedList - 1874 unit tests passing, lint and typecheck clean
- handleOrgAll: apply withOrg mapping so ORG column is populated in paginated output - handleOrgAllIssues: use isMultiProject=true in header (already true in row formatOptions) - displayFetchedItems: add orgSlugForHint field so truncation hint emits valid CLI command - project/list: move resolveCursor inside org-all override closure so ValidationError fires before ContextError - list-command.ts: clean up leftover syntax fragment from reverted bare-slug change - Update PR description: bare slug = project search (consistent across all list commands)
BYK
commented
Feb 18, 2026
- Replace parsed.type ternaries with Extract<> casts in issue/list.ts and project/list.ts override closures
- Fix handleProjectSearch to throw ContextError("Project", ...) instead of ContextError(config.entityName, ...)
- Add List Command Infrastructure section to AGENTS.md documenting list-command.ts and org-list.ts helpers
…ct<> casts ModeHandler<T> now receives ParsedVariant<T> as an argument. The dispatcher passes the correctly-narrowed parsed value, so override closures can access variant-specific fields (.org, .projectSlug) directly without manual casts.
…gCursor project/list.ts had a local resolveCursor that duplicated resolveOrgCursor from db/pagination.ts. Replace the local function and update tests.
- Escape '|' to '%7C' in user-provided query and platform values used in pagination context keys to prevent delimiter injection. - Send query: undefined instead of query: '' when no project or query filter is active in listIssuesPaginated.
BYK
commented
Feb 19, 2026
…licated handler - Extract escapeContextKeyValue() into db/pagination.ts as shared utility for pipe-delimiter escaping in context keys (was inline in issue/list.ts and project/list.ts). - Deduplicate handleResolvedTargets overrides in issue/list.ts: single resolveAndHandle function reused across auto-detect, explicit, and project-search modes instead of three identical closures. - Add explanatory comments for fullQuery || undefined in api-client.ts and for 'Project' ContextError resource in org-list.ts handleProjectSearch.
… variant
Introduces HandlerContext<T> that bundles parsed, stdout, cwd, and flags
into a single object passed to every mode handler. This eliminates the
need for handlers to close over these values from their parent scope.
Commands add extra fields via spread: (ctx) => handle({ ...ctx, extra }).
Also adds a 'fallback' option to DispatchOptions so commands where most
modes share one handler (e.g. issue list) can specify it once instead of
repeating it for each key.
The fallback added complexity for minimal benefit — a shared local handler assigned to each mode key is clearer and just as concise.
Contributor
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
displayFetchedItems was emitting an inline truncation hint via orgSlugForHint AND handleExplicitOrg was writing the same tip again via writeFooter. Remove orgSlugForHint so displayFetchedItems only shows the plain count line; the writeFooter below is the single source for the pagination tip.
BYK
added a commit
that referenced
this pull request
Feb 19, 2026
…265) ## What Two fixes found during post-merge testing of #262: ### CLI-72: `pagination_cursors` wrong primary key Migration 4→5 used `CREATE TABLE IF NOT EXISTS`, so any DB that already had `pagination_cursors` from an earlier code path kept a single-column PK (`command_key TEXT PRIMARY KEY`) instead of the required composite PK (`PRIMARY KEY (command_key, context)`). This caused a runtime crash on the first `--cursor last` use: ``` SQLiteError: ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint ``` **Fix:** - Schema version bumped to 6 with a migration that detects the wrong PK, drops the table, and recreates it correctly. Cursor data loss is safe (5-min TTL). - `repairWrongPrimaryKeys()` added to `repairSchema()` so auto-repair also catches this. - `isSchemaError()` extended to recognise the ON CONFLICT error and trigger auto-repair. - New `wrong_primary_key` `SchemaIssue` variant surfaced in `getSchemaIssues()` and `sentry cli fix`. ### Test isolation: `bun test` caused ~130 spurious failures locally `"test": "bun test"` ran all files in one process. `test/isolated/resolve-target.test.ts` uses `mock.module()` which leaks global module state across files, poisoning `api-client.js`, `db/defaults.js`, and others for all subsequent tests. **Fix:** Change the `test` script to `bun run test:unit && bun run test:isolated` so each suite runs in a separate Bun process. The split was already documented in `AGENTS.md`; the top-level script just wasn't using it. ## Result `bun run test`: 1931 tests, 0 failures (was 130 failures).
3 tasks
This was referenced Feb 23, 2026
BYK
added a commit
that referenced
this pull request
Feb 23, 2026
## Summary `org list` was the only list command not using the shared constants from `list-command.ts` that landed in #262. This switches it over. ## Changes - Replace inline `limit` and `json` flag definitions with `buildListLimitFlag("organizations")` and `LIST_JSON_FLAG` - Add `LIST_BASE_ALIASES` — gives `org list` the missing `-n` shorthand for `--limit`, consistent with all other list commands - Remove now-unused `numberParser` import from `command.ts` No behaviour change beyond the new `-n` alias. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
betegon
pushed a commit
that referenced
this pull request
Feb 26, 2026
## Summary `org list` was the only list command not using the shared constants from `list-command.ts` that landed in #262. This switches it over. ## Changes - Replace inline `limit` and `json` flag definitions with `buildListLimitFlag("organizations")` and `LIST_JSON_FLAG` - Add `LIST_BASE_ALIASES` — gives `org list` the missing `-n` shorthand for `--limit`, consistent with all other list commands - Remove now-unused `numberParser` import from `command.ts` No behaviour change beyond the new `-n` alias. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the pagination and flexible target parsing pattern introduced in #221 for `project list` to all remaining list commands: `issue list`, `team list`, `repo list`, `trace list`, and `log list`. Introduces a shared `dispatchOrgScopedList` infrastructure with `HandlerContext` that all list commands now use.
Changes
Shared infrastructure
Command changes
Tests
Behavior notes