From 8b88a6df1e26a81376f74be865ed73f1b0df8a10 Mon Sep 17 00:00:00 2001 From: Adam Skoufis Date: Sat, 25 Nov 2023 15:00:52 +1100 Subject: [PATCH] Fix package manager detection in non-monorepos --- .changeset/short-schools-report.md | 5 +++ .../sku/config/lintStaged/lintStagedConfig.js | 16 ++++---- packages/sku/lib/packageManager.js | 39 +++++++++++++++---- packages/sku/lib/preCommit.js | 5 ++- 4 files changed, 49 insertions(+), 16 deletions(-) create mode 100644 .changeset/short-schools-report.md diff --git a/.changeset/short-schools-report.md b/.changeset/short-schools-report.md new file mode 100644 index 000000000..045f75363 --- /dev/null +++ b/.changeset/short-schools-report.md @@ -0,0 +1,5 @@ +--- +'sku': patch +--- + +Fix package manager detection in non-monorepos diff --git a/packages/sku/config/lintStaged/lintStagedConfig.js b/packages/sku/config/lintStaged/lintStagedConfig.js index 4bb1ce237..8fb808c1d 100644 --- a/packages/sku/config/lintStaged/lintStagedConfig.js +++ b/packages/sku/config/lintStaged/lintStagedConfig.js @@ -2,16 +2,18 @@ const { isYarn } = require('../../lib/packageManager'); const { lintExtensions } = require('../../lib/lint'); const { getCommand } = require('@antfu/ni'); -const steps = {}; +/** + * @type {import('lint-staged').Config} + */ +const config = { + [`**/*.{${lintExtensions},md,less}`]: ['sku format', 'sku lint'], +}; // Yarn lock integrity check if (isYarn) { - steps['+(package.json|yarn.lock)'] = [ - () => getCommand('yarn', 'install', ['--check-files']), + config['+(package.json|yarn.lock)'] = [ + getCommand('yarn', 'install', ['--check-files']), ]; } -// Format & lint -steps[`**/*.{${lintExtensions},md,less}`] = ['sku format', 'sku lint']; - -module.exports = steps; +module.exports = config; diff --git a/packages/sku/lib/packageManager.js b/packages/sku/lib/packageManager.js index 0db93f844..775a348f4 100644 --- a/packages/sku/lib/packageManager.js +++ b/packages/sku/lib/packageManager.js @@ -1,6 +1,8 @@ +const { existsSync } = require('node:fs'); +const { join } = require('node:path'); const { cwd } = require('../lib/cwd'); const { findRootSync } = require('@manypkg/find-root'); -const { getCommand, INSTALL_PAGE } = require('@antfu/ni'); +const { getCommand, INSTALL_PAGE, LOCKS } = require('@antfu/ni'); const { sync: which } = require('which'); const skuArgs = require('../config/args'); @@ -10,6 +12,19 @@ const skuArgs = require('../config/args'); /** @type {Array} */ const supportedPackageManagers = ['yarn', 'pnpm', 'npm']; +/** @type {Record} */ +const lockfileForPackageManager = Object.fromEntries( + Object.entries(LOCKS) + .filter(([, packageManager]) => + supportedPackageManagers.includes(packageManager), + ) + .map(([lockfileName, packageManager]) => [packageManager, lockfileName]), +); + +const supportedLockfiles = supportedPackageManagers.map( + (packageManager) => lockfileForPackageManager[packageManager], +); + /** * @param {SupportedPackageManager} commandName * @returns {SupportedPackageManager | null} @@ -24,18 +39,28 @@ const detectPackageManager = () => /** * Get the package manager and root directory of the project. If the project does not have a - * project manager configured, a supported package manager will be detected in your `PATH`, and + * package manager configured, a supported package manager will be detected in your `PATH`, and * `rootDir` will be `null`. * @returns {{packageManager: SupportedPackageManager, rootDir: string | null}} */ const getPackageManager = () => { let _packageManager = skuArgs?.packageManager; + // @manypkg/find-root only returns a tool if it finds a monorepo. + // If it finds a regular repo, it will return a 'root' tool, which is absolutely useless. + // So we need to detect the package manager ourselves. I'd use `detect` from from `@antfu/ni` or + // `detect-package-manager`, but they're async only and we can't make getPackageManager async. try { - const { - tool: { type: foundPackageManager }, - rootDir, - } = findRootSync(cwd()); + const { rootDir } = findRootSync(cwd()); + + let foundPackageManager; + + for (const supportedLockfile of supportedLockfiles) { + if (existsSync(join(rootDir, supportedLockfile))) { + foundPackageManager = LOCKS[supportedLockfile]; + break; + } + } if (!supportedPackageManagers.includes(foundPackageManager)) { throw new Error('Unsupported package manager found'); @@ -126,7 +151,7 @@ const getAddCommand = ({ type, logLevel, deps, exact }) => { return getCommand(packageManager, 'add', args); }; -const getInstallCommand = () => getCommand(packageManager, 'install', []); +const getInstallCommand = () => getCommand(packageManager, 'install'); const getWhyCommand = () => { const whyCommand = isPnpm ? 'why -r' : 'why'; diff --git a/packages/sku/lib/preCommit.js b/packages/sku/lib/preCommit.js index bc170e177..d7be11728 100644 --- a/packages/sku/lib/preCommit.js +++ b/packages/sku/lib/preCommit.js @@ -1,11 +1,12 @@ const chalk = require('chalk'); + +const config = require('../config/lintStaged/lintStagedConfig'); const lintStaged = require('lint-staged'); -const configPath = require.resolve('../config/lintStaged/lintStagedConfig'); module.exports = async () => { let success = false; try { - success = await lintStaged({ configPath }); + success = await lintStaged({ config }); } catch (e) { console.error(chalk.red(e)); }