Skip to content

Commit 6870b84

Browse files
fix(cli): format new project command hints with the detected package runner
remove/transfer confirmation nextSteps, transfer recipient errors, the post-transfer workspace-use hint, and provider recovery commands now render through the project's package runner (pnpm dlx / bunx / npx -y with @prisma/cli@latest) instead of the hardcoded prisma-cli bin name, matching the agent group's convention.
1 parent bdd2bda commit 6870b84

2 files changed

Lines changed: 66 additions & 15 deletions

File tree

packages/cli/src/controllers/project.ts

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import {
1414
FileTokenStorage,
1515
WorkspaceSelectionError,
1616
} from "../adapters/token-storage";
17+
import {
18+
type PrismaCliPackageCommandFormatter,
19+
resolvePrismaCliPackageCommandFormatterSync,
20+
} from "../lib/agent/cli-command";
1721
import { createAppProvider } from "../lib/app/app-provider";
1822
import { SERVICE_TOKEN_ENV_VAR } from "../lib/auth/client";
1923
import { requireComputeAuth } from "../lib/auth/guard";
@@ -578,6 +582,9 @@ export async function runProjectRemove(
578582
projectRef: string,
579583
options: ProjectRemoveOptions,
580584
): Promise<CommandSuccess<ProjectRemoveResult>> {
585+
const formatCommand = resolvePrismaCliPackageCommandFormatterSync(
586+
context.runtime.cwd,
587+
);
581588
const authState = await requireAuthenticatedAuthState(context);
582589
const workspace = authState.workspace;
583590
if (!workspace) {
@@ -597,7 +604,13 @@ export async function runProjectRemove(
597604
confirm: options.confirm,
598605
summary: "Confirm project removal",
599606
why: "Removing a project is permanent, deletes its databases, and stops its apps, so it requires the exact project id.",
600-
nextStep: `prisma-cli project remove ${project.id} --confirm ${project.id}`,
607+
nextStep: formatCommand([
608+
"project",
609+
"remove",
610+
project.id,
611+
"--confirm",
612+
project.id,
613+
]),
601614
});
602615

603616
await provider.removeProject({
@@ -627,6 +640,9 @@ export async function runProjectTransfer(
627640
projectRef: string,
628641
options: ProjectTransferOptions,
629642
): Promise<CommandSuccess<ProjectTransferResult>> {
643+
const formatCommand = resolvePrismaCliPackageCommandFormatterSync(
644+
context.runtime.cwd,
645+
);
630646
const authState = await requireAuthenticatedAuthState(context);
631647
const workspace = authState.workspace;
632648
if (!workspace) {
@@ -639,13 +655,21 @@ export async function runProjectTransfer(
639655
"--to-workspace and --recipient-token are mutually exclusive.",
640656
"Pass either --to-workspace <id-or-name> or --recipient-token <token>.",
641657
[
642-
"prisma-cli project transfer <project> --to-workspace <id-or-name> --confirm <project-id>",
658+
formatCommand([
659+
"project",
660+
"transfer",
661+
"<project>",
662+
"--to-workspace",
663+
"<id-or-name>",
664+
"--confirm",
665+
"<project-id>",
666+
]),
643667
],
644668
"project",
645669
);
646670
}
647671
if (!options.toWorkspace?.trim() && !options.recipientToken?.trim()) {
648-
throw transferRecipientRequiredError();
672+
throw transferRecipientRequiredError(formatCommand);
649673
}
650674

651675
const { provider, projects } = await requireProjectMutationContext(
@@ -661,7 +685,7 @@ export async function runProjectTransfer(
661685
confirm: options.confirm,
662686
summary: "Confirm project transfer",
663687
why: "Transferring moves the project to another workspace and this workspace loses access, so it requires the exact project id.",
664-
nextStep: `prisma-cli project transfer ${project.id} ${
688+
nextStep: `${formatCommand(["project", "transfer", project.id])} ${
665689
options.toWorkspace
666690
? `--to-workspace ${formatCommandArgument(options.toWorkspace)}`
667691
: "--recipient-token <token>"
@@ -698,7 +722,7 @@ export async function runProjectTransfer(
698722
warnings,
699723
nextSteps: options.toWorkspace
700724
? [
701-
`prisma-cli auth workspace use ${formatCommandArgument(options.toWorkspace)}`,
725+
`${formatCommand(["auth", "workspace", "use"])} ${formatCommandArgument(options.toWorkspace)}`,
702726
]
703727
: [],
704728
};
@@ -715,6 +739,9 @@ async function resolveTransferRecipient(
715739
context: CommandContext,
716740
options: ProjectTransferOptions,
717741
): Promise<ResolvedTransferRecipient> {
742+
const formatCommand = resolvePrismaCliPackageCommandFormatterSync(
743+
context.runtime.cwd,
744+
);
718745
const recipientToken = options.recipientToken?.trim();
719746
if (recipientToken) {
720747
return {
@@ -730,7 +757,7 @@ async function resolveTransferRecipient(
730757

731758
const workspaceRef = options.toWorkspace?.trim();
732759
if (!workspaceRef) {
733-
throw transferRecipientRequiredError();
760+
throw transferRecipientRequiredError(formatCommand);
734761
}
735762

736763
if (!isRealMode(context)) {
@@ -763,7 +790,7 @@ async function resolveTransferRecipient(
763790
}
764791

765792
if (context.runtime.env[SERVICE_TOKEN_ENV_VAR] !== undefined) {
766-
throw transferRecipientUnavailableError();
793+
throw transferRecipientUnavailableError(formatCommand);
767794
}
768795

769796
try {
@@ -873,6 +900,9 @@ async function requireProjectClient(
873900
function createFixtureProjectProvider(
874901
context: CommandContext,
875902
): ProjectProvider {
903+
const fixtureFormatCommand = resolvePrismaCliPackageCommandFormatterSync(
904+
context.runtime.cwd,
905+
);
876906
return {
877907
async renameProject(options) {
878908
const renamed = context.api.renameProject(
@@ -900,9 +930,9 @@ function createFixtureProjectProvider(
900930
domain: "project",
901931
summary: "Project not found",
902932
why: `No project matched "${options.projectId}".`,
903-
fix: "Pass a project id or name from prisma-cli project list.",
933+
fix: `Pass a project id or name from ${fixtureFormatCommand(["project", "list"])}.`,
904934
exitCode: 1,
905-
nextSteps: ["prisma-cli project list"],
935+
nextSteps: [fixtureFormatCommand(["project", "list"])],
906936
});
907937
}
908938
},
@@ -945,7 +975,9 @@ function requireProjectExactConfirmation(options: {
945975
});
946976
}
947977

948-
function transferRecipientRequiredError(): CliError {
978+
function transferRecipientRequiredError(
979+
formatCommand: PrismaCliPackageCommandFormatter,
980+
): CliError {
949981
return new CliError({
950982
code: "TRANSFER_RECIPIENT_REQUIRED",
951983
domain: "project",
@@ -954,13 +986,23 @@ function transferRecipientRequiredError(): CliError {
954986
fix: "Pass --to-workspace <id-or-name> for a locally authenticated workspace, or --recipient-token <token> for a cross-account transfer.",
955987
exitCode: 2,
956988
nextSteps: [
957-
"prisma-cli auth workspace list",
958-
"prisma-cli project transfer <project> --to-workspace <id-or-name> --confirm <project-id>",
989+
formatCommand(["auth", "workspace", "list"]),
990+
formatCommand([
991+
"project",
992+
"transfer",
993+
"<project>",
994+
"--to-workspace",
995+
"<id-or-name>",
996+
"--confirm",
997+
"<project-id>",
998+
]),
959999
],
9601000
});
9611001
}
9621002

963-
function transferRecipientUnavailableError(): CliError {
1003+
function transferRecipientUnavailableError(
1004+
formatCommand: PrismaCliPackageCommandFormatter,
1005+
): CliError {
9641006
return new CliError({
9651007
code: "TRANSFER_RECIPIENT_UNAVAILABLE",
9661008
domain: "project",
@@ -969,7 +1011,15 @@ function transferRecipientUnavailableError(): CliError {
9691011
fix: "Pass --recipient-token <token> with an access token for the receiving workspace, or unset the service token.",
9701012
exitCode: 1,
9711013
nextSteps: [
972-
"prisma-cli project transfer <project> --recipient-token <token> --confirm <project-id>",
1014+
formatCommand([
1015+
"project",
1016+
"transfer",
1017+
"<project>",
1018+
"--recipient-token",
1019+
"<token>",
1020+
"--confirm",
1021+
"<project-id>",
1022+
]),
9731023
],
9741024
});
9751025
}

packages/cli/src/lib/project/provider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ManagementApiClient } from "@prisma/management-api-sdk";
22

3+
import { formatPrismaCliCommand } from "../../shell/cli-command";
34
import { CliError } from "../../shell/errors";
45
import type { ProjectSummary } from "../../types/project";
56

@@ -141,7 +142,7 @@ export function projectRemoveBlockedError(
141142
`Project "${projectId}" still has active deployments.`,
142143
fix: "Remove the project's apps first, then retry the removal.",
143144
exitCode: 1,
144-
nextSteps: ["prisma-cli app remove --app <name>"],
145+
nextSteps: [formatPrismaCliCommand(["app", "remove", "--app", "<name>"])],
145146
});
146147
}
147148

0 commit comments

Comments
 (0)