Skip to content

Commit 0182d2f

Browse files
betegonclaude
andcommitted
refactor(issue): extract fallback to fix cognitive complexity lint
Extract resolveProjectSearchFallback() from resolveProjectSearch() to bring cognitive complexity from 19 down to under 15. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fbd742d commit 0182d2f

File tree

1 file changed

+58
-43
lines changed

1 file changed

+58
-43
lines changed

src/commands/issue/utils.ts

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,66 @@ async function tryResolveFromAlias(
132132
return { org: projectEntry.orgSlug, issue };
133133
}
134134

135+
/**
136+
* Fallback for when the fast shortid fan-out found no matches.
137+
* Uses findProjectsBySlug to give a precise error ("project not found" vs
138+
* "issue not found") and retries the issue lookup on transient failures.
139+
*/
140+
async function resolveProjectSearchFallback(
141+
projectSlug: string,
142+
suffix: string,
143+
commandHint: string
144+
): Promise<StrictResolvedIssue> {
145+
const { projects } = await findProjectsBySlug(projectSlug.toLowerCase());
146+
147+
if (projects.length === 0) {
148+
throw new ResolutionError(
149+
`Project '${projectSlug}'`,
150+
"not found",
151+
commandHint,
152+
["No project with this slug found in any accessible organization"]
153+
);
154+
}
155+
156+
if (projects.length > 1) {
157+
const orgList = projects.map((p) => p.orgSlug).join(", ");
158+
throw new ResolutionError(
159+
`Project '${projectSlug}'`,
160+
"is ambiguous",
161+
commandHint,
162+
[
163+
`Found in: ${orgList}`,
164+
`Specify the org: sentry issue ... <org>/${projectSlug}-${suffix}`,
165+
]
166+
);
167+
}
168+
169+
// Project exists — retry the issue lookup. The fast path may have failed
170+
// due to a transient error (5xx, timeout); retrying here either succeeds
171+
// or propagates the real error to the user.
172+
const matchedProject = projects[0];
173+
const matchedOrg = matchedProject?.orgSlug;
174+
if (matchedOrg && matchedProject) {
175+
const retryShortId = expandToFullShortId(suffix, matchedProject.slug);
176+
const issue = await getIssueByShortId(matchedOrg, retryShortId);
177+
return { org: matchedOrg, issue };
178+
}
179+
180+
throw new ResolutionError(
181+
`Project '${projectSlug}'`,
182+
"not found",
183+
commandHint
184+
);
185+
}
186+
135187
/**
136188
* Resolve project-search type: search for project across orgs, then fetch issue.
137189
*
138190
* Resolution order:
139191
* 1. Try alias cache (fast, local)
140-
* 2. Search for project across orgs via API
192+
* 2. Check DSN detection cache
193+
* 3. Try shortid endpoint directly across all orgs (fast path)
194+
* 4. Fall back to findProjectsBySlug for precise error messages
141195
*
142196
* @param projectSlug - Project slug to search for
143197
* @param suffix - Issue suffix (uppercase)
@@ -234,48 +288,9 @@ async function resolveProjectSearch(
234288
}
235289
}
236290

237-
// 4. All orgs returned 404 — fall back to findProjectsBySlug for a
238-
// precise error: "project not found" vs "issue not found in project".
239-
const { projects } = await findProjectsBySlug(projectSlug.toLowerCase());
240-
241-
if (projects.length === 0) {
242-
throw new ResolutionError(
243-
`Project '${projectSlug}'`,
244-
"not found",
245-
commandHint,
246-
["No project with this slug found in any accessible organization"]
247-
);
248-
}
249-
250-
if (projects.length > 1) {
251-
const orgList = projects.map((p) => p.orgSlug).join(", ");
252-
throw new ResolutionError(
253-
`Project '${projectSlug}'`,
254-
"is ambiguous",
255-
commandHint,
256-
[
257-
`Found in: ${orgList}`,
258-
`Specify the org: sentry issue ... <org>/${projectSlug}-${suffix}`,
259-
]
260-
);
261-
}
262-
263-
// Project exists — retry the issue lookup. The fast path may have failed
264-
// due to a transient error (5xx, timeout); retrying here either succeeds
265-
// or propagates the real error to the user.
266-
const matchedProject = projects[0];
267-
const matchedOrg = matchedProject?.orgSlug;
268-
if (matchedOrg && matchedProject) {
269-
const retryShortId = expandToFullShortId(suffix, matchedProject.slug);
270-
const issue = await getIssueByShortId(matchedOrg, retryShortId);
271-
return { org: matchedOrg, issue };
272-
}
273-
274-
throw new ResolutionError(
275-
`Project '${projectSlug}'`,
276-
"not found",
277-
commandHint
278-
);
291+
// 4. Fall back to findProjectsBySlug for precise error messages
292+
// and retry the issue lookup (handles transient failures).
293+
return resolveProjectSearchFallback(projectSlug, suffix, commandHint);
279294
}
280295

281296
/**

0 commit comments

Comments
 (0)