{"version":3,"file":"dependencies.mjs","sources":["../../../../src/node/core/dependencies.ts"],"sourcesContent":["import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport semver, { SemVer } from 'semver';\nimport resolveFrom from 'resolve-from';\nimport execa, { CommonOptions, ExecaReturnValue } from 'execa';\nimport readPkgUp, { PackageJson } from 'read-pkg-up';\nimport type { BuildOptions } from '../build';\nimport { getPackageManager } from './managers';\n\n/**\n * From V5 this will be imported from the package.json of `@strapi/strapi`.\n */\nconst PEER_DEPS = {\n react: '^18.0.0',\n 'react-dom': '^18.0.0',\n 'react-router-dom': '^6.0.0',\n 'styled-components': '^6.0.0',\n};\n\ninterface CheckRequiredDependenciesResult {\n didInstall: boolean;\n}\n\ninterface DepToInstall {\n name: string;\n wantedVersion: string;\n declaredVersion?: never;\n}\n\n/**\n * Checks the user's project that it has declared and installed the required dependencies\n * needed by the Strapi admin project. Whilst generally speaking most modules will be\n * declared by the actual packages there are some packages where you only really want one of\n * and thus they are declared as peer dependencies – react / styled-components / etc.\n *\n * If these deps are not installed or declared, then we prompt the user to correct this. In\n * V4 this is not a hard requirement, but in V5 it will be. Might as well get people started now.\n */\nconst checkRequiredDependencies = async ({\n cwd,\n logger,\n}: Pick): Promise => {\n /**\n * This enables us to use experimental deps for libraries like\n * react or styled-components. This is useful for testing against.\n */\n if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {\n logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');\n return { didInstall: false };\n }\n\n const pkg = await readPkgUp({ cwd });\n\n if (!pkg) {\n throw new Error(`Could not find package.json at path: ${cwd}`);\n }\n\n logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);\n\n interface DepToReview {\n name: string;\n wantedVersion: string;\n declaredVersion: string;\n }\n\n /**\n * Run through each of the peer deps and figure out if they need to be\n * installed or they need their version checked against.\n */\n const { install, review } = Object.entries(PEER_DEPS).reduce<{\n install: DepToInstall[];\n review: DepToReview[];\n }>(\n (acc, [name, version]) => {\n if (!pkg.packageJson.dependencies) {\n throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);\n }\n\n const declaredVersion = pkg.packageJson.dependencies[name];\n\n if (!declaredVersion) {\n acc.install.push({\n name,\n wantedVersion: version,\n });\n } else {\n acc.review.push({\n name,\n wantedVersion: version,\n declaredVersion,\n });\n }\n\n return acc;\n },\n {\n install: [],\n review: [],\n }\n );\n\n if (install.length > 0) {\n logger.info(\n 'The Strapi admin needs to install the following dependencies:',\n os.EOL,\n install.map(({ name, wantedVersion }) => ` - ${name}@${wantedVersion}`).join(os.EOL)\n );\n\n await installDependencies(install, {\n cwd,\n logger,\n });\n\n const [file, ...args] = process.argv;\n\n /**\n * Re-run the same command after installation e.g. strapi build because the yarn.lock might\n * not be the same and could break installations. It's not the best solution, but it works.\n */\n await execa(file, args, { cwd, stdio: 'inherit' });\n return { didInstall: true };\n }\n\n if (review.length) {\n const errors: string[] = [];\n\n for (const dep of review) {\n // The version specified in package.json could be incorrect, eg `foo`\n let minDeclaredVersion: SemVer | null = null;\n try {\n minDeclaredVersion = semver.minVersion(dep.declaredVersion);\n } catch (err) {\n // Intentional fall-through (variable will be left as null, throwing below)\n }\n\n if (!minDeclaredVersion) {\n errors.push(\n `The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`\n );\n } else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {\n /**\n * The delcared version should be semver compatible with our required version\n * of the dependency. If it's not, we should advise the user to change it.\n */\n logger.warn(\n [\n `Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n\n const installedVersion = await getModuleVersion(dep.name, cwd);\n\n if (!installedVersion) {\n /**\n * TODO: when we know the packageManager we can advise the actual install command.\n */\n errors.push(\n `The declared dependency, ${dep.name} is not installed. You should install before re-running this command`\n );\n } else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {\n logger.warn(\n [\n `Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n }\n\n if (errors.length > 0 && process.env.NODE_ENV === 'development') {\n throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);\n }\n }\n\n return { didInstall: false };\n};\n\nconst getModule = async (name: string, cwd: string): Promise => {\n const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));\n if (!modulePackagePath) {\n return null;\n }\n const file = await fs.readFile(modulePackagePath, 'utf8').then((res) => JSON.parse(res));\n\n return file;\n};\n\nconst getModuleVersion = async (name: string, cwd: string): Promise => {\n const pkg = await getModule(name, cwd);\n\n return pkg?.version || null;\n};\n\nconst installDependencies = async (\n install: DepToInstall[],\n { cwd, logger }: Pick\n) => {\n const packageManager = getPackageManager();\n\n if (!packageManager) {\n logger.error(\n 'Could not find a supported package manager, please install the dependencies manually.'\n );\n process.exit(1);\n }\n\n const execOptions: CommonOptions<'utf8'> = {\n encoding: 'utf8',\n cwd,\n stdio: 'inherit',\n };\n\n const packages = install.map(({ name, wantedVersion }) => `${name}@${wantedVersion}`);\n\n let result: ExecaReturnValue | undefined;\n\n if (packageManager === 'npm') {\n const npmArgs = ['install', '--legacy-peer-deps', '--save', ...packages];\n logger.info(`Running 'npm ${npmArgs.join(' ')}'`);\n result = await execa('npm', npmArgs, execOptions);\n } else if (packageManager === 'yarn') {\n const yarnArgs = ['add', ...packages];\n logger.info(`Running 'yarn ${yarnArgs.join(' ')}'`);\n result = await execa('yarn', yarnArgs, execOptions);\n } else if (packageManager === 'pnpm') {\n const pnpmArgs = ['add', '--save-prod', ...packages];\n logger.info(`Running 'pnpm ${pnpmArgs.join(' ')}'`);\n result = await execa('pnpm', pnpmArgs, execOptions);\n }\n\n if (result?.exitCode || result?.failed) {\n throw new Error('Package installation failed');\n }\n};\n\nexport { checkRequiredDependencies, getModule };\nexport type { CheckRequiredDependenciesResult, PackageJson };\n"],"names":["PEER_DEPS","react","checkRequiredDependencies","cwd","logger","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","pkg","readPkgUp","Error","debug","os","EOL","packageJson","install","review","Object","entries","reduce","acc","name","version","dependencies","declaredVersion","push","wantedVersion","length","info","map","join","installDependencies","file","args","argv","execa","stdio","errors","dep","minDeclaredVersion","semver","minVersion","err","satisfies","installedVersion","getModuleVersion","NODE_ENV","getModule","modulePackagePath","resolveFrom","silent","path","fs","readFile","then","res","JSON","parse","packageManager","getPackageManager","error","exit","execOptions","encoding","packages","result","npmArgs","yarnArgs","pnpmArgs","exitCode","failed"],"mappings":"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"}