mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-01 08:34:12 +00:00
feat: only show npm flag for react 18 deps (#7573)
* feat: only show npm flag for react 18 deps * tests: update
This commit is contained in:
5
.changeset/shaggy-penguins-vanish.md
Normal file
5
.changeset/shaggy-penguins-vanish.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"shadcn": patch
|
||||
---
|
||||
|
||||
update npm flag
|
||||
@@ -34,7 +34,7 @@ export async function updateDependencies(
|
||||
|
||||
// Offer to use --force or --legacy-peer-deps if using React 19 with npm.
|
||||
let flag = ""
|
||||
if (isUsingReact19(config) && packageManager === "npm") {
|
||||
if (shouldPromptForNpmFlag(config) && packageManager === "npm") {
|
||||
if (options.silent) {
|
||||
flag = "force"
|
||||
} else {
|
||||
@@ -98,12 +98,18 @@ export async function updateDependencies(
|
||||
dependenciesSpinner?.succeed()
|
||||
}
|
||||
|
||||
function isUsingReact19(config: Config) {
|
||||
function shouldPromptForNpmFlag(config: Config) {
|
||||
const packageInfo = getPackageInfo(config.resolvedPaths.cwd, false)
|
||||
|
||||
if (!packageInfo?.dependencies?.react) {
|
||||
return false
|
||||
}
|
||||
|
||||
return /^(?:\^|~)?19(?:\.\d+)*(?:-.*)?$/.test(packageInfo.dependencies.react)
|
||||
const hasReact19 = /^(?:\^|~)?19(?:\.\d+)*(?:-.*)?$/.test(
|
||||
packageInfo.dependencies.react
|
||||
)
|
||||
const hasReactDayPicker8 =
|
||||
packageInfo.dependencies["react-day-picker"]?.startsWith("8")
|
||||
|
||||
return hasReact19 && hasReactDayPicker8
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"author": "shadcn",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react": "19.0.0"
|
||||
"react": "19.0.0",
|
||||
"react-day-picker": "8.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,139 +1,157 @@
|
||||
import { vi, describe, afterEach, test, expect } from "vitest"
|
||||
import { execa } from "execa"
|
||||
import prompts from "prompts"
|
||||
import { updateDependencies } from "../../../src/utils/updaters/update-dependencies"
|
||||
import path from "path"
|
||||
|
||||
vi.mock("execa")
|
||||
vi.mock("prompts")
|
||||
|
||||
describe("updateDependencies", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test.each([
|
||||
{
|
||||
description: "npm without react 19 includes no additional flags",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "npm with react 19 applies force prompt when silent",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "--force", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "--force", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "npm with react 19 prompts for flag when not silent",
|
||||
flagPrompt: "legacy-peer-deps",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "--legacy-peer-deps", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "--legacy-peer-deps", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "deno uses npm: package prefix",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-deno")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "deno",
|
||||
expectedArgs: ["add", "npm:first", "npm:second", "npm:third"],
|
||||
expectedDevArgs: ["add", "-D", "npm:fourth"]
|
||||
},
|
||||
{
|
||||
description: "bun uses bun",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-bun")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "bun",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "pnpm uses pnpm",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-pnpm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "pnpm",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"]
|
||||
},
|
||||
{
|
||||
description: "deduplicates input dependencies",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "first"],
|
||||
devDependencies: ["second", "second"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm")
|
||||
}
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first"],
|
||||
expectedDevArgs: ["install", "-D", "second"]
|
||||
}
|
||||
])("$description", async ({ options, flagPrompt, config, dependencies, devDependencies, expectedPackageManager, expectedArgs, expectedDevArgs }) => {
|
||||
|
||||
vi.mocked(prompts).mockResolvedValue({ flag: flagPrompt })
|
||||
|
||||
await updateDependencies(
|
||||
dependencies,
|
||||
devDependencies,
|
||||
config,
|
||||
options ?? {}
|
||||
)
|
||||
|
||||
if (flagPrompt) {
|
||||
expect(prompts).toHaveBeenCalled()
|
||||
}
|
||||
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(
|
||||
expectedPackageManager,
|
||||
expectedArgs,
|
||||
{ cwd: config?.resolvedPaths.cwd }
|
||||
)
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(
|
||||
expectedPackageManager,
|
||||
expectedDevArgs,
|
||||
{ cwd: config?.resolvedPaths.cwd }
|
||||
)
|
||||
})
|
||||
})
|
||||
import path from "path"
|
||||
import { execa } from "execa"
|
||||
import prompts from "prompts"
|
||||
import { afterEach, describe, expect, test, vi } from "vitest"
|
||||
|
||||
import { updateDependencies } from "../../../src/utils/updaters/update-dependencies"
|
||||
|
||||
vi.mock("execa")
|
||||
vi.mock("prompts")
|
||||
|
||||
describe("updateDependencies", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
|
||||
test.each([
|
||||
{
|
||||
description:
|
||||
"npm without react-day-picker v8 includes no additional flags",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "-D", "fourth"],
|
||||
},
|
||||
{
|
||||
description:
|
||||
"npm with react-day-picker v8 applies force prompt when silent",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "--force", "first", "second", "third"],
|
||||
expectedDevArgs: ["install", "--force", "-D", "fourth"],
|
||||
},
|
||||
{
|
||||
description:
|
||||
"npm with react-day-picker v8 prompts for flag when not silent",
|
||||
flagPrompt: "legacy-peer-deps",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm-react19"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: [
|
||||
"install",
|
||||
"--legacy-peer-deps",
|
||||
"first",
|
||||
"second",
|
||||
"third",
|
||||
],
|
||||
expectedDevArgs: ["install", "--legacy-peer-deps", "-D", "fourth"],
|
||||
},
|
||||
{
|
||||
description: "deno uses npm: package prefix",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-deno"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "deno",
|
||||
expectedArgs: ["add", "npm:first", "npm:second", "npm:third"],
|
||||
expectedDevArgs: ["add", "-D", "npm:fourth"],
|
||||
},
|
||||
{
|
||||
description: "bun uses bun",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-bun"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "bun",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"],
|
||||
},
|
||||
{
|
||||
description: "pnpm uses pnpm",
|
||||
dependencies: ["first", "second", "third"],
|
||||
devDependencies: ["fourth"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-pnpm"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "pnpm",
|
||||
expectedArgs: ["add", "first", "second", "third"],
|
||||
expectedDevArgs: ["add", "-D", "fourth"],
|
||||
},
|
||||
{
|
||||
description: "deduplicates input dependencies",
|
||||
options: { silent: true },
|
||||
dependencies: ["first", "first"],
|
||||
devDependencies: ["second", "second"],
|
||||
config: {
|
||||
resolvedPaths: {
|
||||
cwd: path.resolve(__dirname, "../../fixtures/project-npm"),
|
||||
},
|
||||
},
|
||||
expectedPackageManager: "npm",
|
||||
expectedArgs: ["install", "first"],
|
||||
expectedDevArgs: ["install", "-D", "second"],
|
||||
},
|
||||
])(
|
||||
"$description",
|
||||
async ({
|
||||
options,
|
||||
flagPrompt,
|
||||
config,
|
||||
dependencies,
|
||||
devDependencies,
|
||||
expectedPackageManager,
|
||||
expectedArgs,
|
||||
expectedDevArgs,
|
||||
}) => {
|
||||
vi.mocked(prompts).mockResolvedValue({ flag: flagPrompt })
|
||||
|
||||
await updateDependencies(
|
||||
dependencies,
|
||||
devDependencies,
|
||||
config,
|
||||
options ?? {}
|
||||
)
|
||||
|
||||
if (flagPrompt) {
|
||||
expect(prompts).toHaveBeenCalled()
|
||||
}
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(expectedPackageManager, expectedArgs, {
|
||||
cwd: config?.resolvedPaths.cwd,
|
||||
})
|
||||
|
||||
expect(execa).toHaveBeenCalledWith(
|
||||
expectedPackageManager,
|
||||
expectedDevArgs,
|
||||
{ cwd: config?.resolvedPaths.cwd }
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user