Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions helpers/compile/plugins/resolvePathsPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,22 @@ async function bundleImport(importPath: string, external: string[] = []) {
describe('resolvePathsPlugin', () => {
it.each([
['prisma', 'packages/cli/src/types.ts'],
['prisma7', 'packages/prisma7/src/index.ts'],
['@prisma/prisma7', 'packages/prisma7/src/index.ts'],
['prisma/config', 'packages/cli/src/config.ts'],
['prisma7/config', 'packages/prisma7/src/config.ts'],
['@prisma/prisma7/config', 'packages/prisma7/src/config.ts'],
])('resolves %s to %s', async (importPath, resolvedPath) => {
const result = await bundleImport(importPath)

expect(Object.keys(result.metafile.inputs)).toContain(resolvedPath)
})

it('preserves exact external aliases', async () => {
const result = await bundleImport('prisma/config', ['prisma/config'])
it.each([
['prisma/config', 'packages/cli/src/config.ts'],
['@prisma/prisma7/config', 'packages/prisma7/src/config.ts'],
])('preserves exact external alias %s', async (importPath, resolvedPath) => {
const result = await bundleImport(importPath, [importPath])

expect(Object.keys(result.metafile.inputs)).not.toContain('packages/cli/src/config.ts')
expect(result.outputFiles[0]?.text).toContain('import "prisma/config";')
expect(Object.keys(result.metafile.inputs)).not.toContain(resolvedPath)
expect(result.outputFiles[0]?.text).toContain(`import "${importPath}";`)
})
})
8 changes: 4 additions & 4 deletions packages/cli/src/Generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { version as cliVersion } from '../package.json'
import { introspectSql, sqlDirPath } from './generate/introspectSql'
import { Watcher } from './generate/Watcher'
import { breakingChangesMessage } from './utils/breakingChanges'
import type { CliDistributionIdentity } from './utils/cli-distribution-identity'
import { type CliDistributionIdentity, getCliDistributionPackageName } from './utils/cli-distribution-identity'
import {
getGlobalLocalVersionMismatchWarning as getDefaultGlobalLocalVersionMismatchWarning,
type GlobalLocalVersionMismatchWarningOptions,
Expand Down Expand Up @@ -250,9 +250,9 @@ ${breakingChangesMessage}`
const versionsOutOfSync = clientGeneratorVersion && cliVersion !== clientGeneratorVersion
const versionsWarning =
versionsOutOfSync && logger.should.warn()
? `\n\n${yellow(bold('warn'))} Versions of ${bold(`${this.identity}@${cliVersion}`)} and ${bold(
`@prisma/client@${clientGeneratorVersion}`,
)} don't match.
? `\n\n${yellow(bold('warn'))} Versions of ${bold(
`${getCliDistributionPackageName(this.identity)}@${cliVersion}`,
)} and ${bold(`@prisma/client@${clientGeneratorVersion}`)} don't match.
This might lead to unexpected behavior.
Please make sure they have the same version.`
: ''
Expand Down
11 changes: 8 additions & 3 deletions packages/cli/src/Init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ import { installSkills } from './init/skill-install'
import { login } from './management-api/auth'
import { createAuthenticatedManagementAPI } from './management-api/auth-client'
import { FileTokenStorage } from './management-api/token-storage'
import type { CliDistributionIdentity } from './utils/cli-distribution-identity'
import {
type CliDistributionIdentity,
getCliDistributionConfigPackageName,
getCliDistributionPackageName,
} from './utils/cli-distribution-identity'
import { determineClientOutputPath } from './utils/client-output-path'
import { printError } from './utils/prompt/utils/print'

Expand Down Expand Up @@ -233,7 +237,8 @@ type DefaultConfigInput = {
}

export const defaultConfig = ({ prismaFolder, runtime, identity }: DefaultConfigInput) => {
const configPackage = `${identity}/config`
const configPackage = getCliDistributionConfigPackageName(identity)
const packageName = getCliDistributionPackageName(identity)
const schemaPath = path.relative(process.cwd(), path.join(prismaFolder, 'schema.prisma'))
const migrationsPath = path.relative(process.cwd(), path.join(prismaFolder, 'migrations'))

Expand All @@ -257,7 +262,7 @@ export default defineConfig({
.otherwise(() => {
return `\
// This file was generated by Prisma, and assumes you have installed the following:
// npm install --save-dev ${identity} dotenv
// npm install --save-dev ${packageName} dotenv
import "dotenv/config";
import { defineConfig } from "${configPackage}";

Expand Down
30 changes: 30 additions & 0 deletions packages/cli/src/__tests__/Init.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,36 @@ test('is schema and env written on disk replace', async () => {
`)
})

test('prisma7 init writes scoped config package and keeps prisma7 commands', async () => {
ctx.fixture('init')
const recordedStdout = stripAnsi(
(
await Init.new('prisma7').parse(['--datasource-provider', 'sqlite', '--no-skills'], defaultTestConfig())
).toString(),
)

const config = fs.readFileSync(join(ctx.tmpDir, 'prisma.config.ts'), 'utf-8')
expect(config).toMatchInlineSnapshot(`
"// This file was generated by Prisma, and assumes you have installed the following:
// npm install --save-dev @prisma/prisma7 dotenv
import \"dotenv/config\";
import { defineConfig } from \"@prisma/prisma7/config\";

export default defineConfig({
schema: \"prisma/schema.prisma\",
migrations: {
path: \"prisma/migrations\",
},
datasource: {
url: process.env[\"DATABASE_URL\"],
},
});
"
`)
expect(recordedStdout).toContain('Run prisma7 db pull to introspect your database.')
expect(recordedStdout).not.toContain('Run prisma db pull to introspect your database.')
})

test('works with url param', async () => {
ctx.fixture('init')
const recordedStdout = (await Init.new('prisma').parse(['--url', 'file:dev.db'], defaultTestConfig())).toString()
Expand Down
22 changes: 20 additions & 2 deletions packages/cli/src/__tests__/globalLocalVersionMismatch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ describe('getGlobalLocalVersionMismatchWarning', () => {
expect(result).toContain('@prisma/client@7.3.0')
})

test('warns with the scoped prisma7 package name and prisma7 command guidance', async () => {
const result = await buildWarning({
identity: 'prisma7',
getInstalledPackageVersion: (packageName) =>
Promise.resolve(packageName === '@prisma/prisma7' ? '7.4.0' : GLOBAL_VERSION),
})

expect(result).toContain('@prisma/prisma7@7.5.0')
expect(result).toContain('@prisma/prisma7@7.4.0')
expect(result).not.toContain('The globally installed prisma7@7.5.0')
expect(result).toContain('npx prisma7 generate')
})

test('returns null for an empty global version', async () => {
const getInstalledPackageVersion = jest.fn()
const result = await buildWarning({
Expand All @@ -102,21 +115,26 @@ describe('getInstalledPackageVersionFromNodeModules', () => {
await fs.promises.rm(tempDir, { force: true, recursive: true })
})

test('reads local prisma and @prisma/client versions from an ancestor node_modules directory', async () => {
test('reads local prisma, @prisma/prisma7, and @prisma/client versions from an ancestor node_modules directory', async () => {
const schemaRootDir = path.join(tempDir, 'prisma')
await fs.promises.mkdir(schemaRootDir)
await writePackageVersion('prisma', '7.4.0')
await writePackageVersion('@prisma/prisma7', '7.4.1')
await writePackageVersion('@prisma/client', '7.3.0')

await expect(getInstalledPackageVersionFromNodeModules('prisma', schemaRootDir)).resolves.toBe('7.4.0')
await expect(getInstalledPackageVersionFromNodeModules('@prisma/prisma7', schemaRootDir)).resolves.toBe('7.4.1')
await expect(getInstalledPackageVersionFromNodeModules('@prisma/client', schemaRootDir)).resolves.toBe('7.3.0')
})

test('returns null when the package cannot be resolved', async () => {
await expect(getInstalledPackageVersionFromNodeModules('prisma', tempDir)).resolves.toBeNull()
})

async function writePackageVersion(packageName: 'prisma' | '@prisma/client', version: string): Promise<void> {
async function writePackageVersion(
packageName: 'prisma' | '@prisma/prisma7' | '@prisma/client',
version: string,
): Promise<void> {
const packageDir = path.join(tempDir, 'node_modules', ...packageName.split('/'))
await fs.promises.mkdir(packageDir, { recursive: true })
await fs.promises.writeFile(path.join(packageDir, 'package.json'), JSON.stringify({ version }), 'utf-8')
Expand Down
10 changes: 5 additions & 5 deletions packages/cli/src/bootstrap/Bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Init } from '../Init'
import { Link, type LinkResult } from '../postgres/link/Link'
import { isAlreadyLinked } from '../postgres/link/local-setup'
import { LinkApiError, sanitizeErrorMessage } from '../postgres/link/management-api'
import type { CliDistributionIdentity } from '../utils/cli-distribution-identity'
import { type CliDistributionIdentity, getCliDistributionPackageName } from '../utils/cli-distribution-identity'
import { type BootstrapStepStatus, formatBootstrapOutput } from './completion-output'
import { detectProjectState, getModelNames, getSeedCommand } from './project-state'
import { emitFlowCompleted, emitFlowStarted, emitStepCompleted, emitStepFailed, emitStepSkipped } from './telemetry'
Expand Down Expand Up @@ -128,7 +128,7 @@ export class Bootstrap implements Command {
baseDir: string,
): Promise<string | HelpError> {
const flowStart = performance.now()
const cliPackage = this.identity
const cliPackage = getCliDistributionPackageName(this.identity)
const stepsCompleted: string[] = []
const steps: BootstrapStepStatus = {
init: 'skipped',
Expand Down Expand Up @@ -186,12 +186,12 @@ export class Bootstrap implements Command {
templateScaffolded = steps.template === 'completed'
if (!templateScaffolded) {
return new HelpError(
`\n${bold(red('!'))} Template download failed and no project exists to fall back to.\n\nInitialize a project first, then re-run ${bold(`${this.identity} bootstrap`)}:\n ${dim('$')} npm init -y ${dim(' (or pnpm init / yarn init / bun init)')}\n ${dim('$')} npx ${this.identity} bootstrap`,
`\n${bold(red('!'))} Template download failed and no project exists to fall back to.\n\nInitialize a project first, then re-run ${bold(`${this.identity} bootstrap`)}:\n ${dim('$')} npm init -y ${dim(' (or pnpm init / yarn init / bun init)')}\n ${dim('$')} npx ${getCliDistributionPackageName(this.identity)}@latest bootstrap`,
)
}
} else {
return new HelpError(
`\n${bold(red('!'))} Cannot proceed without a project.\n\nInitialize a project first, then re-run ${bold(`${this.identity} bootstrap`)}:\n ${dim('$')} npm init -y ${dim(' (or pnpm init / yarn init / bun init)')}\n ${dim('$')} npx ${this.identity} bootstrap`,
`\n${bold(red('!'))} Cannot proceed without a project.\n\nInitialize a project first, then re-run ${bold(`${this.identity} bootstrap`)}:\n ${dim('$')} npm init -y ${dim(' (or pnpm init / yarn init / bun init)')}\n ${dim('$')} npx ${getCliDistributionPackageName(this.identity)}@latest bootstrap`,
)
}
} else if (templateName) {
Expand Down Expand Up @@ -321,7 +321,7 @@ export class Bootstrap implements Command {
: `${pm} add -D ${missingDevDeps.join(' ')}`
console.log(` ${dim('$')} ${installHint}`)
}
console.log(` ${dim('$')} npx ${this.identity}@latest bootstrap`)
console.log(` ${dim('$')} npx ${getCliDistributionPackageName(this.identity)}@latest bootstrap`)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

return formatBootstrapOutput({
databaseId: telemetryCtx.linkResult?.databaseId ?? databaseId ?? 'unknown',
Expand Down
25 changes: 24 additions & 1 deletion packages/cli/src/bootstrap/__tests__/Bootstrap.vitest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,29 @@ describe('Bootstrap command — help and validation', () => {
})

describe('Bootstrap command — new project flow', () => {
test.each([
{ args: [], templateFailure: false },
{ args: ['--template', 'nextjs'], templateFailure: true },
])('uses the scoped package in empty-project prisma7 recovery', async ({ args, templateFailure }) => {
const { confirm } = await import('@inquirer/prompts')
vi.mocked(confirm).mockResolvedValue(false)

if (templateFailure) {
const { downloadAndExtractTemplate } = await import('../template-scaffold')
vi.mocked(downloadAndExtractTemplate).mockRejectedValueOnce(new Error('Network error'))
}

const result = await Bootstrap.new('prisma7').parse(
['--api-key', 'test_key', '--database', 'db_abc123', ...args],
defaultTestConfig(),
tmpDir,
)

expect(result).toBeInstanceOf(HelpError)
expect((result as HelpError).message).toContain('npx @prisma/prisma7@latest bootstrap')
expect((result as HelpError).message).not.toContain('npx prisma7 bootstrap')
})

test('runs init when user declines template, then links', async () => {
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"test"}', 'utf-8')
fs.mkdirSync(path.join(tmpDir, 'node_modules', 'dotenv'), { recursive: true })
Expand Down Expand Up @@ -280,7 +303,7 @@ describe('Bootstrap command — existing project flow', () => {
fs.mkdirSync(path.join(tmpDir, 'node_modules', '.bin'), { recursive: true })
fs.writeFileSync(path.join(tmpDir, 'node_modules', '.bin', 'prisma7.cmd'), '', 'utf-8')
fs.mkdirSync(path.join(tmpDir, 'node_modules', 'dotenv'), { recursive: true })
fs.mkdirSync(path.join(tmpDir, 'node_modules', 'prisma7'), { recursive: true })
fs.mkdirSync(path.join(tmpDir, 'node_modules', '@prisma', 'prisma7'), { recursive: true })
fs.mkdirSync(path.join(tmpDir, 'node_modules', '@prisma', 'client'), { recursive: true })

const { confirm } = await import('@inquirer/prompts')
Expand Down
10 changes: 7 additions & 3 deletions packages/cli/src/bootstrap/completion-output.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getCommandWithExecutor } from '@prisma/internals'
import { bold, dim, green, red } from 'kleur/colors'

import type { CliDistributionIdentity } from '../utils/cli-distribution-identity'
import { type CliDistributionIdentity, getCliDistributionPackageName } from '../utils/cli-distribution-identity'

type StepResult = 'completed' | 'skipped' | 'not-applicable' | 'failed'

Expand Down Expand Up @@ -64,9 +64,13 @@ export function formatBootstrapOutput(opts: {
if (opts.pendingDepsInstall) {
lines.push(bold('Next steps:'))
lines.push(
` 1. Install ${bold('@prisma/client')}, ${bold('dotenv')}, and ${bold(cliCommand)} with your package manager`,
` 1. Install ${bold('@prisma/client')}, ${bold('dotenv')}, and ${bold(
getCliDistributionPackageName(cliCommand),
)} with your package manager`,
)
lines.push(
` 2. Re-run ${green(`npx ${getCliDistributionPackageName(cliCommand)}@latest bootstrap`)} to finish setup`,
)
lines.push(` 2. Re-run ${green(`npx ${cliCommand}@latest bootstrap`)} to finish setup`)
lines.push('')
return lines.join('\n')
}
Expand Down
11 changes: 11 additions & 0 deletions packages/cli/src/utils/cli-distribution-identity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'node:path'

export type CliDistributionIdentity = 'prisma' | 'prisma7'
export type CliDistributionPackageName = 'prisma' | '@prisma/prisma7'

/** Returns the CLI distribution selected by the executable that Node invoked. */
export function getCliDistributionIdentity(executedScript = process.argv[1]): CliDistributionIdentity {
Expand All @@ -9,3 +10,13 @@ export function getCliDistributionIdentity(executedScript = process.argv[1]): Cl

return stem === 'prisma7' ? 'prisma7' : 'prisma'
}

export function getCliDistributionPackageName(identity: CliDistributionIdentity): CliDistributionPackageName {
return identity === 'prisma7' ? '@prisma/prisma7' : 'prisma'
}

export function getCliDistributionConfigPackageName(
identity: CliDistributionIdentity,
): `${CliDistributionPackageName}/config` {
return `${getCliDistributionPackageName(identity)}/config`
}
12 changes: 8 additions & 4 deletions packages/cli/src/utils/global-local-version-mismatch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import fs from 'fs'
import { bold, yellow } from 'kleur/colors'
import path from 'path'

import type { CliDistributionIdentity } from './cli-distribution-identity'
import {
type CliDistributionIdentity,
type CliDistributionPackageName,
getCliDistributionPackageName,
} from './cli-distribution-identity'

type LocalPackageName = CliDistributionIdentity | '@prisma/client'
type LocalPackageName = CliDistributionPackageName | '@prisma/client'

export type GlobalLocalVersionMismatchWarningOptions = {
cwd?: string
Expand All @@ -22,7 +26,7 @@ type LocalPackageVersionMismatch = {
}

function getLocalPackageNames(identity: CliDistributionIdentity): LocalPackageName[] {
return [identity, '@prisma/client']
return [getCliDistributionPackageName(identity), '@prisma/client']
}

export async function getGlobalLocalVersionMismatchWarning(
Expand Down Expand Up @@ -109,7 +113,7 @@ function formatGlobalLocalVersionMismatchWarning(
const packageLabel = mismatches.length === 1 ? 'package' : 'packages'

return `${yellow(bold('warn'))} The globally installed ${bold(
`${identity}@${globalVersion}`,
`${getCliDistributionPackageName(identity)}@${globalVersion}`,
)} does not match the local ${packageLabel} ${localVersions} installed in this project.
This may generate Prisma Client artifacts that are incompatible with the local runtime.
Run ${bold(`npx ${identity} generate`)} to use the local Prisma CLI, or align your global and local Prisma versions.`
Expand Down
32 changes: 20 additions & 12 deletions packages/client/tests/e2e/_utils/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,20 @@ async function main() {

console.log('🎠 Preparing e2e tests')

let allPackageFolderNames = await fs.readdir(path.join(monorepoRoot, 'packages'))
allPackageFolderNames = allPackageFolderNames.filter((p) => !p.includes('DS_Store'))
const packagesDir = path.join(monorepoRoot, 'packages')
const allPackageFolderNames = (await fs.readdir(packagesDir)).filter((folderName) =>
existsSync(path.join(packagesDir, folderName, 'package.json')),
)
const allPackageFolders = allPackageFolderNames.map((folderName) => path.join(packagesDir, folderName))
const allPkgJsonPaths = allPackageFolders.map((packageFolder) => path.join(packageFolder, 'package.json'))
const allPkgJson = allPkgJsonPaths.map(
(packageJsonPath) =>
require(packageJsonPath) as {
name: string
dependencies?: Record<string, string>
},
Comment on lines +69 to +74

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

pnpm typecheck

Repository: prisma/prisma

Length of output: 13232


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- target file ---'
sed -n '1,115p' packages/client/tests/e2e/_utils/run.ts

printf '%s\n' '--- package and compiler configuration ---'
cat package.json
find . -maxdepth 3 \( -name 'tsconfig*.json' -o -name 'package.json' \) -print | sort | head -80
rg -n '"typecheck"|strictNullChecks|strict" packages/client package.json tsconfig*.json . --glob 'tsconfig*.json' --glob 'package.json' --glob '!node_modules' | head -120

Repository: prisma/prisma

Length of output: 12866


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- client package scripts ---'
cat packages/client/package.json

printf '%s\n' '--- client compiler settings ---'
cat packages/client/tsconfig.json
cat packages/client/tsconfig.build.json 2>/dev/null || true

printf '%s\n' '--- workspace typecheck scripts ---'
rg -n '"typecheck"|strictNullChecks|strict' --glob 'package.json' --glob 'tsconfig*.json' packages pnpm-workspace.yaml turbo.json

printf '%s\n' '--- available TypeScript compiler ---'
command -v tsc || true
test -x node_modules/.bin/tsc && node_modules/.bin/tsc --version || true

Repository: prisma/prisma

Length of output: 13559


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- inherited workspace compiler settings ---'
cat tsconfig.json

printf '%s\n' '--- exact-expression compiler probe ---'
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/probe.ts" <<'TS'
declare const allPkgJson: Array<{
  name: string
  dependencies?: Record<string, string>
}>

declare const i: number
declare const key: string

for (const key of Object.keys(allPkgJson[i].dependencies ?? {})) {
  allPkgJson[i].dependencies[key] = `/tmp/${key}`
}
TS

tsc --noEmit --strictNullChecks --skipLibCheck "$tmpdir/probe.ts" 2>&1 || true

printf '%s\n' '--- narrowed-expression compiler probe ---'
cat >"$tmpdir/probe-fixed.ts" <<'TS'
declare const allPkgJson: Array<{
  name: string
  dependencies?: Record<string, string>
}>

declare const i: number

const packageJson = allPkgJson[i]
const dependencies = packageJson.dependencies
if (dependencies !== undefined) {
  for (const key of Object.keys(dependencies)) {
    dependencies[key] = `/tmp/${key}`
  }
}
TS

tsc --noEmit --strictNullChecks --skipLibCheck "$tmpdir/probe-fixed.ts"

Repository: prisma/prisma

Length of output: 1036


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- inherited strictness ---'
cat tsconfig.utils.typecheck.json

printf '%s\n' '--- exact-expression compiler probe ---'
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/probe.ts" <<'TS'
declare const allPkgJson: Array<{
  name: string
  dependencies?: Record<string, string>
}>

declare const i: number

for (const key of Object.keys(allPkgJson[i].dependencies ?? {})) {
  allPkgJson[i].dependencies[key] = `/tmp/${key}`
}
TS

tsc --ignoreConfig --noEmit --strictNullChecks --skipLibCheck "$tmpdir/probe.ts" 2>&1 || true

printf '%s\n' '--- narrowed-expression compiler probe ---'
cat >"$tmpdir/probe-fixed.ts" <<'TS'
declare const allPkgJson: Array<{
  name: string
  dependencies?: Record<string, string>
}>

declare const i: number

const packageJson = allPkgJson[i]
const dependencies = packageJson.dependencies
if (dependencies !== undefined) {
  for (const key of Object.keys(dependencies)) {
    dependencies[key] = `/tmp/${key}`
  }
}
TS

tsc --ignoreConfig --noEmit --strictNullChecks --skipLibCheck "$tmpdir/probe-fixed.ts"

Repository: prisma/prisma

Length of output: 481


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

cat tsconfig.build.bundle.json

Repository: prisma/prisma

Length of output: 2925


Narrow dependencies before assigning to it.

dependencies is optional. The current assignment produces TS2532: Object is possibly 'undefined'. Guard dependencies or store it in a narrowed local before the loop.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/client/tests/e2e/_utils/run.ts` around lines 69 - 74, Update the
package metadata handling around allPkgJson so the optional dependencies
property is narrowed before any assignment or mutation. Guard each package’s
dependencies or assign a narrowed local within the relevant loop, while
preserving the existing dependency updates for packages that declare
dependencies.

Source: Coding guidelines

)
const packedPackageFilename = (packageName: string) => `${packageName.replace(/^@/, '').replace('/', '-')}-0.0.0.tgz`

const prismaTmpDir = path.join(os.homedir(), '.local', 'share', 'prisma-tmp')

Expand All @@ -70,16 +82,13 @@ async function main() {
await $`pnpm -r exec cp package.json package.copy.json`

// we prepare to replace references to local packages with their tarballs names
const localPackageNames = [...allPackageFolderNames.map((p) => `@prisma/${p}`), 'prisma', 'prisma7']
const allPackageFolders = allPackageFolderNames.map((p) => path.join(monorepoRoot, 'packages', p))
const allPkgJsonPaths = allPackageFolders.map((p) => path.join(p, 'package.json'))
const allPkgJson = allPkgJsonPaths.map((p) => require(p))
const localPackageNames = allPkgJson.map((packageJson) => packageJson.name)

// replace references to unbundled local packages with built and packaged tarballs
for (let i = 0; i < allPkgJson.length; i++) {
for (const key of Object.keys(allPkgJson[i].dependencies ?? {})) {
if (localPackageNames.includes(key)) {
allPkgJson[i].dependencies[key] = `/tmp/${key.replace('@prisma/', 'prisma-')}-0.0.0.tgz`
allPkgJson[i].dependencies[key] = `/tmp/${packedPackageFilename(key)}`
}
}

Expand Down Expand Up @@ -121,11 +130,10 @@ async function main() {
const dockerVolumeOptions = process.platform === 'linux' ? ':z' : ''
const dockerVolume = (source: string, target: string) => `${source}:${target}${dockerVolumeOptions}`
const dockerVolumes = [
dockerVolume(`${prismaTmpDir}/prisma-0.0.0.tgz`, '/tmp/prisma-0.0.0.tgz'), // hardcoded because folder doesn't match name
dockerVolume(`${prismaTmpDir}/prisma7-0.0.0.tgz`, '/tmp/prisma7-0.0.0.tgz'),
...allPackageFolderNames
.filter((p) => p !== 'prisma7')
.map((p) => dockerVolume(`${prismaTmpDir}/prisma-${p}-0.0.0.tgz`, `/tmp/prisma-${p}-0.0.0.tgz`)),
...allPkgJson.map(({ name }) => {
const filename = packedPackageFilename(name)
return dockerVolume(`${prismaTmpDir}/${filename}`, `/tmp/${filename}`)
}),
dockerVolume(path.join(monorepoRoot, 'packages', 'engines'), '/engines'),
dockerVolume(path.join(monorepoRoot, 'packages', 'client'), '/client'),
dockerVolume(e2eRoot, '/e2e'),
Expand Down
Loading
Loading