diff --git a/packages/cli/src/commands/explore.ts b/packages/cli/src/commands/explore.ts index f9d21594e..add55320f 100644 --- a/packages/cli/src/commands/explore.ts +++ b/packages/cli/src/commands/explore.ts @@ -49,8 +49,11 @@ import { listSupportedReplayFields, parseReplayEnvironmentFilter, } from "../lib/replay-search.js"; -import { resolveOrgOptionalFromArg } from "../lib/resolve-target.js"; import { sanitizeQuery } from "../lib/search-query.js"; +import { + type OrgOptionalTarget, + orgOptionalTarget, +} from "../lib/target-positional.js"; import { appendPeriodHint, PERIOD_BRIEF, @@ -697,7 +700,7 @@ export const exploreCommand = buildListCommand("explore", { placeholder: "target", brief: "Target: /, /, or . Auto-detected if omitted.", - parse: String, + parse: orgOptionalTarget, optional: true as const, }, ], @@ -773,13 +776,12 @@ export const exploreCommand = buildListCommand("explore", { n: "limit", }, }, - async *func(this: SentryContext, flags: ExploreFlags, target?: string) { - const { cwd } = this; - const { org, project } = await resolveOrgOptionalFromArg( - target, - cwd, - "explore", - ); + async *func( + this: SentryContext, + flags: ExploreFlags, + target: OrgOptionalTarget, + ) { + const { org, project } = await target.resolved; let dataset = flags.dataset; const userSuppliedFields = flags.field && flags.field.length > 0; diff --git a/packages/cli/test/commands/explore.test.ts b/packages/cli/test/commands/explore.test.ts index fa68161e4..fcb7b9fb3 100644 --- a/packages/cli/test/commands/explore.test.ts +++ b/packages/cli/test/commands/explore.test.ts @@ -87,6 +87,7 @@ function createContext() { }), }, cwd: "/tmp/test-explore", + commandPrefix: ["sentry", "explore"], }, getStdout: () => stdoutChunks.join(""), }; @@ -150,8 +151,8 @@ beforeEach(async () => { nextCursor: undefined, }); - // Default: resolveOrgOptionalFromArg returns org-only (auto-detect) - resolveTargetSpy = vi.spyOn(resolveTarget, "resolveOrgOptionalFromArg"); + // Default: resolveOrgOptionalTarget returns org-only (auto-detect) + resolveTargetSpy = vi.spyOn(resolveTarget, "resolveOrgOptionalTarget"); resolveTargetSpy.mockResolvedValue({ org: "test-org" }); resolveCursorSpy = vi.spyOn(paginationDb, "resolveCursor").mockReturnValue({ @@ -209,7 +210,7 @@ describe("sentry explore", () => { await func.call(context, DEFAULT_FLAGS, "my-org/"); expect(resolveTargetSpy).toHaveBeenCalledWith( - "my-org/", + { type: "org-all", org: "my-org" }, "/tmp/test-explore", "explore", ); @@ -257,7 +258,7 @@ describe("sentry explore", () => { await func.call(context, DEFAULT_FLAGS, "cli"); expect(resolveTargetSpy).toHaveBeenCalledWith( - "cli", + { type: "project-search", projectSlug: "cli" }, "/tmp/test-explore", "explore", ); @@ -274,7 +275,7 @@ describe("sentry explore", () => { await func.call(context, DEFAULT_FLAGS); expect(resolveTargetSpy).toHaveBeenCalledWith( - undefined, + { type: "auto-detect" }, "/tmp/test-explore", "explore", ); diff --git a/packages/cli/test/lib/complete.test.ts b/packages/cli/test/lib/complete.test.ts index 29632c043..c4790195a 100644 --- a/packages/cli/test/lib/complete.test.ts +++ b/packages/cli/test/lib/complete.test.ts @@ -93,6 +93,12 @@ describe("getCompletions: context detection", () => { expect(result.some((c) => c.value === "test-org/")).toBe(true); }); + test("returns org/project completions for the top-level explore command", async () => { + await seedOrgs([{ slug: "my-org", name: "My Organization" }]); + const result = getCompletions(["explore"], ""); + expect(result.some((c) => c.value === "my-org/")).toBe(true); + }); + test("returns org-only completions for team list", async () => { await seedOrgs([{ slug: "acme", name: "Acme Inc" }]); const result = getCompletions(["team", "list"], "");