Files
orca/mobile/src/source-control/mobile-pr-create.ts
T
Neil 755c1562c3 fix(lint): enable anti-slop/no-pass-through-type-alias
`anti-slop/no-pass-through-type-alias` rejects a type alias whose entire
right-hand side is a bare reference to another named type, including the
generic form where every type parameter is forwarded positionally and
unchanged (`type A<T> = B<T>`). Those aliases add a second name for one
type: readers have to resolve the indirection, "go to definition" lands on
a rename rather than the shape, and the two names drift apart in review.

Flipped the rule from "off" to "error" in `config/oxlint-anti-slop.json`
and fixed all 195 violations reported across `src`, `config`, `tests`, and
`mobile`.

Fix approach, in order of preference per site:

- Delete the alias and use the target type directly at every reference,
  updating imports. This covers the large majority of the 195.
- Where the alias name was the better or more widely used name, rename the
  target declaration to the alias name instead of renaming call sites (for
  example `GitUncommittedEntry` -> `GitStatusEntry` in
  `src/shared/git-status-types.ts`).
- Where a pass-through sat in front of a type that was itself only used
  through that alias, collapse the pair into a single declaration that
  keeps the real shape (intersection, `Pick`/`Omit`, or union) under one
  name.

No alias was converted into an equivalent `interface X extends Y` to dodge
the rule, and no new pass-through was introduced.

No suppressions were added. The vendored anti-slop plugin source under
`config/oxlint-plugins/anti-slop/` is excluded from the audit by the
`--ignore-pattern` flag in `audit:anti-slop`, and stays byte-identical to
upstream.

Verified:

- `npx oxlint --config config/oxlint-anti-slop.json --ignore-pattern
  'config/oxlint-plugins/anti-slop/**' src config tests mobile` exits 0 (195 -> 0; baseline counted on a scratch worktree of
  `nwparker/2x-lint` with the rule flipped on).
- `node config/scripts/run-typecheck-projects-in-parallel.mjs` exits 0.
- `cd mobile && pnpm typecheck` exits 0 (the parallel script covers only the
  three desktop tsconfigs).
- Root vitest over the changed files and their sibling tests: 210 files,
  4072 passed, 1 skipped.
- Mobile vitest over the changed files and their sibling tests: 36 files,
  445 passed.
- `npx oxlint` with the repo's default config over every changed file
  (root and mobile) exits 0.
- `npx oxfmt --write` run over the changed files in both workspaces.
2026-09-14 17:14:11 -07:00

80 lines
3.4 KiB
TypeScript

import { hostedReviewCopy } from './hosted-review-copy'
import {
buildMobileHostedReviewCreateParams,
createMobileHostedReview,
mobileRepoSelectorFromWorktreeId,
resolveMobileHostedReviewPrefill,
shouldPushBeforeMobileHostedReviewCreate,
type MobileHostedReviewCreateOutcome,
type MobileHostedReviewPrefill
} from './mobile-hosted-review-service'
export {
buildMobileHostedReviewCreateParams as buildMobilePrCreateParams,
createMobileHostedReview as createMobilePr,
mobileRepoSelectorFromWorktreeId,
resolveMobileHostedReviewPrefill as resolveMobilePrPrefill,
shouldPushBeforeMobileHostedReviewCreate as shouldPushBeforeMobilePrCreate
}
export function getMobilePrCreateSuccessWarning(
outcome: Extract<MobileHostedReviewCreateOutcome, { ok: true }>,
provider: MobileHostedReviewPrefill['provider']
): string | undefined {
const copy = hostedReviewCopy(provider)
if (outcome.existing) {
return outcome.number
? `${copy.titleLabel} #${outcome.number} is already open.`
: `${copy.titleLabel} is already open.`
}
if (outcome.linkError) {
return `${copy.titleLabel} created, but Orca could not refresh it yet.`
}
return undefined
}
export function getMobilePrCreateBlockMessage(prefill: MobileHostedReviewPrefill): string | null {
const copy = hostedReviewCopy(prefill.provider)
if (prefill.canCreate !== false || shouldPushBeforeMobileHostedReviewCreate(prefill)) {
// Fail closed: only an accepted no-review lookup (`not_found`) may open
// Create / Push & Create. `unavailable`, `found`, or a missing outcome (an
// older host that predates the field) all leave review existence unproven —
// mobile has no refresh/review-lookup signal of its own, so it must not
// offer create, or the needs_push Push & Create path would slip through.
if (prefill.reviewLookupOutcome !== 'not_found') {
return `Orca could not confirm whether this branch already has a ${copy.reviewLabel}. Try again in a moment.`
}
return null
}
switch (prefill.blockedReason) {
case 'dirty':
return `Commit changes before creating a ${copy.reviewLabel}.`
case 'detached_head':
return `Check out a branch before creating a ${copy.reviewLabel}.`
case 'default_branch':
return `Switch to a feature branch before creating a ${copy.reviewLabel}.`
case 'no_upstream':
return `Publish commits before creating a ${copy.reviewLabel}.`
case 'needs_sync':
return `Sync this branch before creating a ${copy.reviewLabel}.`
case 'auth_required':
return `Authenticate before creating a ${copy.reviewLabel}.`
case 'unsupported_provider':
return `Creating ${copy.reviewLabel}s is not supported for this repo.`
case 'existing_review':
return `A ${copy.reviewLabel} already exists for this branch.`
case 'fork_head_unsupported':
return `Creating a ${copy.reviewLabel} from this fork is not supported.`
case 'base_not_on_remote':
return `Push the base branch before creating a ${copy.reviewLabel}.`
case 'needs_push':
case null:
case undefined:
return `This branch is not ready for a ${copy.reviewLabel} yet.`
default:
// Why: desktop can add blocked reasons before a long-lived mobile branch
// catches up; remain safely blocked while preserving merge-ref typechecks.
return `This branch is not ready for a ${copy.reviewLabel} yet.`
}
}