Skip to main content
Glama
reuvenaor

Shadcn Registry manager

by reuvenaor
update-dependencies.ts4.85 kB
import { RegistryItem } from "@/src/registry/schema" import { updateDependenciesOptionsSchema } from "@/src/schemas/update.schemas" import { Config } from "@/src/utils/get-config" import { getPackageInfo } from "@/src/utils/get-package-info" import { getPackageManager } from "@/src/utils/get-package-manager" import { logger } from "@/src/utils/logger" import { spinner } from "@/src/utils/spinner" import { secureExeca, secureNpmInstall } from "@/src/utils/secure-exec" import { RequestHandlerExtra } from "@modelcontextprotocol/sdk/shared/protocol" import { ServerRequest, ServerNotification } from "@modelcontextprotocol/sdk/types" import { z } from "zod" export async function updateDependencies( dependencies: RegistryItem["dependencies"], devDependencies: RegistryItem["devDependencies"], config: Config, options: z.infer<typeof updateDependenciesOptionsSchema>, extra?: RequestHandlerExtra<ServerRequest, ServerNotification> ) { dependencies = Array.from(new Set(dependencies)) devDependencies = Array.from(new Set(devDependencies)) if (!dependencies?.length && !devDependencies?.length) { return } const validatedOptions = updateDependenciesOptionsSchema.parse(options) const dependenciesSpinner = spinner(`Installing dependencies.`, extra, "update-dependencies").start() const packageManager = await getUpdateDependenciesPackageManager(config) // Offer to use --force or --legacy-peer-deps if using React 19 with pnpm. let flag = "" if (shouldPromptForNpmFlag(config) && (packageManager === "pnpm" || packageManager === "npm")) { if (validatedOptions.silent) { flag = "force" } else { dependenciesSpinner.stopAndPersist() logger.warn( "\nIt looks like you are using React 19. \nSome packages may fail to install due to peer dependency issues in pnpm (see https://ui.shadcn.com/react-19).\n" ) if (validatedOptions.flag) { flag = validatedOptions.flag } } } dependenciesSpinner?.start() await installWithPackageManager( packageManager, dependencies, devDependencies, config.resolvedPaths.cwd, flag ) dependenciesSpinner?.succeed() } function shouldPromptForNpmFlag(config: Config) { const packageInfo = getPackageInfo(config.resolvedPaths.cwd, false) if (!packageInfo?.dependencies?.react) { return false } const hasReact19 = /^(?:\^|~)?19(?:\.\d+)*(?:-.*)?$/.test( packageInfo.dependencies.react ) const hasReactDayPicker8 = packageInfo.dependencies["react-day-picker"]?.startsWith("8") return hasReact19 && hasReactDayPicker8 } async function getUpdateDependenciesPackageManager(config: Config) { const expoVersion = getPackageInfo(config.resolvedPaths.cwd, false) ?.dependencies?.expo if (expoVersion) { // Ensures package versions match the React Native version. // https://docs.expo.dev/more/expo-cli/#install return "expo" } return getPackageManager(config.resolvedPaths.cwd) } async function installWithPackageManager( packageManager: Awaited< ReturnType<typeof getUpdateDependenciesPackageManager> >, dependencies: string[], devDependencies: string[], cwd: string, flag?: string ) { if (packageManager === "pnpm") { return secureNpmInstall("pnpm", dependencies, devDependencies, cwd, flag ? [`--${flag}`] : []) } if (packageManager === "npm") { return secureNpmInstall("npm", dependencies, devDependencies, cwd, flag ? [`--${flag}`] : []) } if (packageManager === "deno") { return installWithDeno(dependencies, devDependencies, cwd) } if (packageManager === "expo") { return installWithExpo(dependencies, devDependencies, cwd) } // Handle other package managers with secure execution if (dependencies?.length) { await secureExeca(packageManager as string, ["add", ...dependencies], { cwd, }) } if (devDependencies?.length) { await secureExeca(packageManager as string, ["add", "-D", ...devDependencies], { cwd }) } } // Note: installWithNpm and installWithPnpm are now replaced by secureNpmInstall async function installWithDeno( dependencies: string[], devDependencies: string[], cwd: string ) { if (dependencies?.length) { await secureExeca("deno", ["add", ...dependencies.map((dep) => `pnpm:${dep}`)], { cwd, }) } if (devDependencies?.length) { await secureExeca( "deno", ["add", "-D", ...devDependencies.map((dep) => `pnpm:${dep}`)], { cwd } ) } } async function installWithExpo( dependencies: string[], devDependencies: string[], cwd: string ) { if (dependencies.length) { await secureExeca("npx", ["expo", "install", ...dependencies], { cwd }) } if (devDependencies.length) { await secureExeca("npx", ["expo", "install", "-- -D", ...devDependencies], { cwd, }) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/reuvenaor/shadcn-registry-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server