diff --git a/src/tasks/deploy-with-composer.ts b/src/tasks/deploy-with-composer.ts index 8e8bcb3..76e08b4 100644 --- a/src/tasks/deploy-with-composer.ts +++ b/src/tasks/deploy-with-composer.ts @@ -3,7 +3,6 @@ import { execa } from "execa"; import { createInterface } from "node:readline"; import type { Writable } from "node:stream"; -import { PRISMA_PLATFORM_CLI_PACKAGE } from "../constants/dependencies"; import { ClassifiedCreateError, getCreateFailureReason, @@ -13,8 +12,8 @@ import { import type { PackageManager } from "../types"; import { getErrorMessage, redactSecrets } from "../utils/errors"; import { - getPackageExecutionArgs, - getPackageExecutionCommand, + getLocalPackageBinaryArgs, + getLocalPackageBinaryCommand, getRunScriptArgs, getRunScriptCommand, } from "../utils/package-manager"; @@ -149,7 +148,7 @@ export function parsePrismaCliEnvelope( } function getPrismaCliArgs(packageManager: PackageManager, args: string[]) { - return getPackageExecutionArgs(packageManager, [PRISMA_PLATFORM_CLI_PACKAGE, ...args]); + return getLocalPackageBinaryArgs(packageManager, "prisma", args); } async function runPrismaJsonCommand(options: { @@ -251,8 +250,7 @@ async function ensureAuthentication(options: { const authState = await whoami(); if (authState.authenticated) return authState; - const loginCommand = getPackageExecutionCommand(options.packageManager, [ - PRISMA_PLATFORM_CLI_PACKAGE, + const loginCommand = getLocalPackageBinaryCommand(options.packageManager, "prisma", [ "auth", "login", ]); @@ -517,8 +515,7 @@ export async function deployNewProjectWithComposer(options: { clearProgress(); failureStage = "composer_deploy"; failureReason = "composer_deploy_failed"; - const deployCommand = getPackageExecutionCommand(options.packageManager, [ - PRISMA_PLATFORM_CLI_PACKAGE, + const deployCommand = getLocalPackageBinaryCommand(options.packageManager, "prisma", [ "deploy", "module.ts", ]); diff --git a/src/tasks/setup-prisma.ts b/src/tasks/setup-prisma.ts index 4ace2e3..0e94b63 100644 --- a/src/tasks/setup-prisma.ts +++ b/src/tasks/setup-prisma.ts @@ -3,7 +3,6 @@ import fs from "fs-extra"; import path from "node:path"; import type { Writable } from "node:stream"; -import { PRISMA_DENO_CLI_PACKAGE, PRISMA_PLATFORM_CLI_PACKAGE } from "../constants/dependencies"; import { ClassifiedCreateError, CreateCancellationError, @@ -29,7 +28,7 @@ import { getErrorMessage } from "../utils/errors"; import { detectPackageManager, getInstallCommand, - getPackageExecutionArgs, + getLocalPackageBinaryArgs, getRunScriptCommand, } from "../utils/package-manager"; import { runSetupCommand } from "../utils/run-command"; @@ -229,10 +228,8 @@ function getInitTarget(provider: DatabaseProvider): "postgres" | "mongodb" { return provider === "mongo" ? "mongodb" : "postgres"; } -function getPrismaCliInvocation(packageManager: PackageManager, args: string[]) { - const packageName = - packageManager === "deno" ? PRISMA_DENO_CLI_PACKAGE : PRISMA_PLATFORM_CLI_PACKAGE; - return getPackageExecutionArgs(packageManager, [packageName, ...args]); +function getInstalledPrismaCliInvocation(packageManager: PackageManager, args: string[]) { + return getLocalPackageBinaryArgs(packageManager, "prisma", args); } async function runPrismaInit(context: PrismaSetupContext, projectDir: string): Promise { @@ -249,7 +246,7 @@ async function runPrismaInit(context: PrismaSetupContext, projectDir: string): P getContractPath(context.authoring), "--skip-install", ]; - const invocation = getPrismaCliInvocation(context.packageManager, args); + const invocation = getInstalledPrismaCliInvocation(context.packageManager, args); if (context.verbose) { log.step(`Running ${[invocation.command, ...invocation.args].join(" ")}`, { output: context.output, @@ -272,7 +269,7 @@ async function initializeAgentSkills( ): Promise { if (context.packageManager === "deno") return; - const invocation = getPrismaCliInvocation(context.packageManager, [ + const invocation = getInstalledPrismaCliInvocation(context.packageManager, [ "init", "--yes", "--no-interactive", @@ -342,7 +339,7 @@ async function runPrismaCli( projectDir: string, args: string[], ): Promise { - const invocation = getPrismaCliInvocation(context.packageManager, args); + const invocation = getInstalledPrismaCliInvocation(context.packageManager, args); if (context.verbose) { log.step([invocation.command, ...invocation.args].join(" "), { output: context.output }); } @@ -454,12 +451,31 @@ export async function executePrismaSetupContext( : (options.progressSpinner ?? spinner({ output: context.output })); const ownsProgress = progress !== undefined && !options.progressSpinner; let gitInitialization: GitInitializationResult | undefined; - let setupStage: CreateFailureStage = "initialize_prisma"; - let setupReason: CreateFailureReason = "prisma_init_failed"; + let setupStage: CreateFailureStage = "configure_project"; + let setupReason: CreateFailureReason = "project_configuration_failed"; if (ownsProgress) progress.start("Creating Prisma 8 project..."); try { + await writePrismaDependencies( + context.databaseProvider, + context.packageManager, + context.authoring, + projectDir, + ); + + progress?.message( + `Installing dependencies with ${getInstallCommand(context.packageManager)}...`, + ); + setupStage = "install_dependencies"; + setupReason = "dependency_install_failed"; + await installProjectDependencies(context.packageManager, projectDir, { + verbose: context.verbose, + json: context.json, + }); + progress?.message("Preparing Prisma 8 project files..."); + setupStage = "initialize_prisma"; + setupReason = "prisma_init_failed"; await runPrismaInit(context, projectDir); setupStage = "configure_project"; @@ -472,12 +488,6 @@ export async function executePrismaSetupContext( authoring: context.authoring, packageManager: context.packageManager, }); - await writePrismaDependencies( - context.databaseProvider, - context.packageManager, - context.authoring, - projectDir, - ); await ensureComposerTypeScriptOptions(projectDir); if (context.databaseProvider === "mongo") await ensureMongoEnvironment(projectDir); if (context.packageManager !== "deno") { @@ -485,16 +495,6 @@ export async function executePrismaSetupContext( await ensureGitignoreEntry(projectDir, "/.prisma-composer"); } - progress?.message( - `Installing dependencies with ${getInstallCommand(context.packageManager)}...`, - ); - setupStage = "install_dependencies"; - setupReason = "dependency_install_failed"; - await installProjectDependencies(context.packageManager, projectDir, { - verbose: context.verbose, - json: context.json, - }); - progress?.message("Installing Prisma agent skills..."); setupStage = "initialize_agent_skills"; setupReason = "agent_skills_init_failed"; diff --git a/src/utils/package-manager.ts b/src/utils/package-manager.ts index 155467a..9569143 100644 --- a/src/utils/package-manager.ts +++ b/src/utils/package-manager.ts @@ -258,7 +258,7 @@ export function getLocalPackageBinaryArgs( case "deno": return { command: "deno", - args: ["run", "-A", DENO_ALLOW_FRESH_DEPENDENCIES, `npm:${binaryName}`, ...binaryArgs], + args: ["run", "-A", "--frozen", `npm:${binaryName}@latest`, ...binaryArgs], }; case "pnpm": return { command: "pnpm", args: ["exec", binaryName, ...binaryArgs] }; @@ -268,7 +268,10 @@ export function getLocalPackageBinaryArgs( return { command: "bun", args: [binaryName, ...binaryArgs] }; case "npm": default: - return { command: "npm", args: ["exec", binaryName, "--", ...binaryArgs] }; + return { + command: "npm", + args: ["exec", "--offline", "--yes=false", "--", binaryName, ...binaryArgs], + }; } } diff --git a/tests/e2e/create-prisma.e2e.test.ts b/tests/e2e/create-prisma.e2e.test.ts index 11c759d..7cf4048 100644 --- a/tests/e2e/create-prisma.e2e.test.ts +++ b/tests/e2e/create-prisma.e2e.test.ts @@ -267,7 +267,7 @@ describe("create-prisma e2e", () => { expect(JSON.parse(stdout)).toMatchObject({ schemaVersion: 1, ok: false, - error: { stage: "initialize_prisma" }, + error: { stage: "install_dependencies" }, }); expect(stderr).toBe(""); expect(await pathExists(path.join(rootDir, "failed-app", "package.json"))).toBe(true); diff --git a/tests/install.test.ts b/tests/install.test.ts index 171adfc..3c3ebbc 100644 --- a/tests/install.test.ts +++ b/tests/install.test.ts @@ -13,6 +13,7 @@ import { import { authoringStyles, createTemplates, databaseProviders, packageManagers } from "../src/types"; import { getInstallArgs, + getLocalPackageBinaryArgs, getPackageExecutionArgs, getRunScriptCommand, } from "../src/utils/package-manager"; @@ -134,6 +135,17 @@ describe("Composer package-manager commands", () => { args: ["run", "-A", "--minimum-dependency-age=0", "npm:prisma@8.0.0-rc.11", "orm", "init"], }); }); + + test("runs the installed Prisma CLI without registry fallback", () => { + expect(getLocalPackageBinaryArgs("npm", "prisma", ["contract", "emit"])).toEqual({ + command: "npm", + args: ["exec", "--offline", "--yes=false", "--", "prisma", "contract", "emit"], + }); + expect(getLocalPackageBinaryArgs("deno", "prisma", ["contract", "emit"])).toEqual({ + command: "deno", + args: ["run", "-A", "--frozen", "npm:prisma@latest", "contract", "emit"], + }); + }); }); describe("generated templates", () => {