Skip to content

feat(cli): add domains transfer command for same-store project moves#3089

Merged
jorgemoya merged 4 commits into
canaryfrom
jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli
Jul 10, 2026
Merged

feat(cli): add domains transfer command for same-store project moves#3089
jorgemoya merged 4 commits into
canaryfrom
jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli

Conversation

@jorgemoya

@jorgemoya jorgemoya commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Linear: LTRAC-1117

What/Why?

Adds catalyst domains transfer <domain> — moves a custom domain from its current project to another project in the same store. This is the same-store counterpart to domains claim (cross-store): when you domains add a domain already bound to another project in your store, the API tells you to use transfer.

  • Source project = the linked project (--project-uuid); destination = --to-project-uuid.
  • Interactive when --to-project-uuid is omitted: fetches the store's projects and prompts you to pick one, excluding the source (mirrors the project picker used by project link / deploy). Pass the flag for non-interactive/CI use.
  • After a successful transfer it shows the domain's status against the destination project, with --wait to poll until it leaves pending.

Client: transferDomainPOST /…/projects/{source}/domains/{domain}/transfer with { new_project_uuid }. Clear errors use UserActionableError (from #3088, now merged) so a bad destination or "no other projects" prints plainly without the Correlation ID / support framing; API 4xx errors flow through the shared assertDomainResponse.

Pre-flight ownership check (follow-up)

transfer moves a domain from the linked (source) project. If the linked project doesn't own the domain, the API rejected the transfer with an opaque domain is not owned by the specified project error — and only after the user had already picked a destination. Added a findDomain client (a getDomain that returns null on a 404 instead of throwing) and a pre-flight that runs before the destination prompt: it confirms the domain is on the source project.

When the linked project doesn't own the domain, the pre-flight now scans the store's other projects and names the one that actually owns it, printing the exact --project-uuid command to re-run. (An earlier version pointed users at domains list, which is dead-end guidance — list only shows the current project's domains, so it can never surface a domain that lives elsewhere.) If no project in the store owns it, it says so and points at domains claim for the cross-store case. The transfer is never attempted and the picker never opens on failure.

Logging polish (follow-up)

  • Disabled consola's per-line wall-clock timestamp (formatOptions: { date: false }). It added noise, and on long lines consola couldn't right-align it so it fell back to an inline [time] prefix that broke copy-pasteable command suggestions. The logs command is unaffected — its timestamps come from the log payload, not consola's clock.
  • Command suggestions in the add/claim "already in use" branches now print on their own unprefixed consola.log line, so they stay clean to copy at any terminal width.

Testing

pnpm typecheck, pnpm lint, domains.spec.ts (43 passing, incl. transfer + pre-flight). New tests: request shape; --to-project-uuid (no prompt); interactive selection excludes the source; destination==source rejected; no-other-projects error; findDomain returns/null/throws; transfer names the owning project (and never calls the API or prompts) when the domain is on a different project; transfer errors when the domain is on no project in the store. Verified domains transfer --help and timestamp-free output on the built CLI.

Migration

None. Docs: documented in docs-v2 #332 (alongside claim).

@jorgemoya jorgemoya requested a review from a team as a code owner July 8, 2026 19:09
@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f82d65b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@bigcommerce/catalyst Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Jul 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
catalyst Ready Ready Preview, Comment Jul 9, 2026 3:59pm

Request Review

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Report

Comparing against baseline from 2b7f2cc (2026-07-09).

No bundle size changes detected.

Base automatically changed from jorgemoya/ltrac-1106-implement-domain-claiming-functionality-in-the-cli to canary July 8, 2026 19:46
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Unlighthouse Performance Comparison — Vercel

Comparing PR preview deployment Unlighthouse scores vs production Unlighthouse scores.

Summary Score

Aggregate score across all categories as reported by Unlighthouse.

Prod Desktop Prod Mobile Preview Desktop Preview Mobile
Score 89 92 92 94

Category Scores

Category Prod Desktop Prod Mobile Preview Desktop Preview Mobile
Performance 73 93 71 76
Accessibility 95 92 95 95
Best Practices 100 100 100 100
SEO 88 100 88 100

Core Web Vitals

Metric Prod Desktop Prod Mobile Preview Desktop Preview Mobile
LCP 5.1 s 3.2 s 5.4 s 6.6 s
CLS 0.037 0 0.037 0
FCP 1.1 s 1.2 s 1.2 s 1.2 s
TBT 0 ms 0 ms 0 ms 0 ms
Max Potential FID 40 ms 60 ms 30 ms 50 ms
Time to Interactive 5.1 s 3.8 s 5.4 s 6.6 s

Full Unlighthouse report →

@jorgemoya jorgemoya force-pushed the jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli branch from 915ddb2 to 6fb0d10 Compare July 8, 2026 20:01
@jorgemoya jorgemoya force-pushed the jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli branch from 6fb0d10 to d811f05 Compare July 8, 2026 22:32
@jorgemoya jorgemoya force-pushed the jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli branch from d811f05 to 24fa1b5 Compare July 9, 2026 14:47
@jorgemoya

Copy link
Copy Markdown
Contributor Author

Testing:

~/dev/catalyst/core on  jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli [✘!?⇡]
❯ node ../packages/catalyst/dist/cli.js domains add www.jorgemoya.dev --api-host api.staging.zone --wait
◢ @bigcommerce/catalyst v1.0.0

◐ Adding domain www.jorgemoya.dev...

 WARN  www.jorgemoya.dev is already bound to another project in this store.

ℹ To move it to this project, run:
  catalyst domains transfer www.jorgemoya.dev --project-uuid 3a80d4b4-59fd-11f1-ba17-d262eb0b9665 --to-project-uuid 8ee5b216-4e4d-11f1-be39-3283882cc9fe

~/dev/catalyst/core on  jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli [✘!?]
❯ node ../packages/catalyst/dist/cli.js domains transfer www.jorgemoya.dev --api-host api.staging.zone
◢ @bigcommerce/catalyst v1.0.0

◐ Checking www.jorgemoya.dev on the current project...
◐ Locating the project that owns www.jorgemoya.dev...

 WARN  www.jorgemoya.dev is on project "jm-load-testing-staging-2" (3a80d4b4-59fd-11f1-ba17-d262eb0b9665), not the current project.

ℹ Re-run the transfer from that project:
  catalyst domains transfer www.jorgemoya.dev --project-uuid 3a80d4b4-59fd-11f1-ba17-d262eb0b9665

~/dev/catalyst/core on  jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli [✘!?]
❯ node ../packages/catalyst/dist/cli.js project link --api-host api.staging.zone
◢ @bigcommerce/catalyst v1.0.0

◐ Fetching projects...
✔ Projects fetched.
✔ Select a project or create a new project (Press <enter> to select). jm-load-testing-staging-2
◐ Writing project UUID to .bigcommerce/project.json...
✔ Project UUID written to .bigcommerce/project.json.

~/dev/catalyst/core on  jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli [✘!?] took 3s
❯ node ../packages/catalyst/dist/cli.js domains transfer www.jorgemoya.dev --api-host api.staging.zone
◢ @bigcommerce/catalyst v1.0.0

◐ Checking www.jorgemoya.dev on the current project...
✔ www.jorgemoya.dev found on the current project.
◐ Fetching projects...
✔ Projects fetched.
✔ Select the project to transfer www.jorgemoya.dev to (Press <enter> to select). jm-load-testing-staging
◐ Transferring domain www.jorgemoya.dev...
✔ Domain www.jorgemoya.dev transferred.
www.jorgemoya.dev active

~/dev/catalyst/core on  jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli [✘!?] took 12s

jorgemoya and others added 4 commits July 9, 2026 10:57
Add `catalyst domains transfer <domain>` to move a custom domain from its
current project to another project in the same store — the same-store
counterpart to `domains claim` (cross-store). The source is the linked project;
the destination is `--to-project-uuid`, or, when that's omitted, chosen
interactively from the store's other projects (the source is excluded).

Adds a `transferDomain` client (`POST .../domains/{domain}/transfer` with
`{ new_project_uuid }`), the subcommand with `--wait`, a default MSW handler,
and tests.

Refs LTRAC-1117
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`domains transfer` moves a domain from the linked (source) project to a
destination. When the linked project doesn't own the domain, the Domains API
rejected the transfer with an opaque "domain is not owned by the specified
project" error — after the user had already picked a destination.

Add a `findDomain` client (a `getDomain` that returns null on a 404 instead of
throwing) and a pre-flight in the transfer command: before prompting for a
destination, confirm the domain is on the source project, otherwise throw an
actionable error pointing at `--project-uuid` and `catalyst domains list`.

Refs LTRAC-1117
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
consola's fancy reporter printed a per-line wall-clock timestamp. It adds
noise for a short-lived CLI (no comparable dev CLI does it), and on long lines
consola can't right-align it, so it falls back to an inline `[time]` prefix
that breaks copy-pasteable command suggestions. Disable it with
`formatOptions: { date: false }`. The `logs` command is unaffected: its
timestamps come from the log payload, not consola's clock.

Also move the runnable command in the add/claim "already in use" error
branches onto its own unprefixed `consola.log` line so it stays clean to copy
at any terminal width.

Refs LTRAC-1117
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The transfer pre-flight told the user to run `catalyst domains list` to find
which project owns the domain, but `list` only shows the *current* project's
domains — so it could never surface a domain that lives on another project.

When the linked project doesn't own the domain, scan the store's other
projects and name the one that does, with the exact `--project-uuid` command
to re-run. If no project in the store owns it, say so and point at
`catalyst domains claim` for the cross-store case.

Refs LTRAC-1117
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jorgemoya jorgemoya force-pushed the jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli branch from c30d407 to f82d65b Compare July 9, 2026 15:58
@jorgemoya jorgemoya enabled auto-merge July 10, 2026 14:16
@jorgemoya jorgemoya added this pull request to the merge queue Jul 10, 2026
Merged via the queue into canary with commit 8d9f9a9 Jul 10, 2026
28 of 30 checks passed
@jorgemoya jorgemoya deleted the jorgemoya/ltrac-1117-add-catalyst-domains-transfer-command-to-the-cli branch July 10, 2026 14:48
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.

2 participants