mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Detect used package manager in extension CLI (#15909)
* Detect used package manager in extension CLI * Add tests Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
committed by
GitHub
parent
0bb34f0f0d
commit
5d25c19836
@@ -44,6 +44,9 @@
|
||||
"build": "run-p \"build:* {@}\"",
|
||||
"build:esm": "tsc --project ./tsconfig.json --module ES2015 --outDir ./dist/esm",
|
||||
"build:cjs": "tsc --project ./tsconfig.json --module CommonJS --outDir ./dist/cjs",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"cleanup": "rimraf ./dist",
|
||||
"dev": "pnpm build -- -w --preserveWatchOutput --incremental"
|
||||
},
|
||||
@@ -70,9 +73,11 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/inquirer": "8.2.1",
|
||||
"@vitest/coverage-c8": "0.25.2",
|
||||
"npm-run-all": "4.1.5",
|
||||
"rimraf": "3.0.2",
|
||||
"typescript": "4.9.3"
|
||||
"typescript": "4.9.3",
|
||||
"vitest": "0.25.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
|
||||
@@ -25,6 +25,7 @@ import execa from 'execa';
|
||||
import ora from 'ora';
|
||||
import copyTemplate from './helpers/copy-template';
|
||||
import detectJsonIndent from '../utils/detect-json-indent';
|
||||
import getPackageManager from '../utils/get-package-manager';
|
||||
|
||||
export default async function add(): Promise<void> {
|
||||
const extensionPath = process.cwd();
|
||||
@@ -126,7 +127,9 @@ export default async function add(): Promise<void> {
|
||||
|
||||
await fse.writeJSON(packagePath, newExtensionManifest, { spaces: indent ?? '\t' });
|
||||
|
||||
await execa('npm', ['install'], { cwd: extensionPath });
|
||||
const packageManager = getPackageManager();
|
||||
|
||||
await execa(packageManager, ['install'], { cwd: extensionPath });
|
||||
|
||||
spinner.succeed(chalk.bold('Done'));
|
||||
} else {
|
||||
@@ -263,7 +266,9 @@ export default async function add(): Promise<void> {
|
||||
|
||||
await fse.writeJSON(packagePath, newExtensionManifest, { spaces: indent ?? '\t' });
|
||||
|
||||
await execa('npm', ['install'], { cwd: extensionPath });
|
||||
const packageManager = getPackageManager();
|
||||
|
||||
await execa(packageManager, ['install'], { cwd: extensionPath });
|
||||
|
||||
spinner.succeed(chalk.bold('Done'));
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { isLanguage, languageToShort } from '../utils/languages';
|
||||
import getSdkVersion from '../utils/get-sdk-version';
|
||||
import getExtensionDevDeps from './helpers/get-extension-dev-deps';
|
||||
import copyTemplate from './helpers/copy-template';
|
||||
import getPackageManager from '../utils/get-package-manager';
|
||||
|
||||
type CreateOptions = { language?: string };
|
||||
|
||||
@@ -88,11 +89,13 @@ async function createPackageExtension({
|
||||
|
||||
await fse.writeJSON(path.join(targetPath, 'package.json'), packageManifest, { spaces: '\t' });
|
||||
|
||||
await execa('npm', ['install'], { cwd: targetPath });
|
||||
const packageManager = getPackageManager();
|
||||
|
||||
await execa(packageManager, ['install'], { cwd: targetPath });
|
||||
|
||||
spinner.succeed(chalk.bold('Done'));
|
||||
|
||||
log(getDoneMessage(type, targetDir, targetPath));
|
||||
log(getDoneMessage(type, targetDir, targetPath, packageManager));
|
||||
}
|
||||
|
||||
async function createLocalExtension({
|
||||
@@ -141,11 +144,13 @@ async function createLocalExtension({
|
||||
|
||||
await fse.writeJSON(path.join(targetPath, 'package.json'), packageManifest, { spaces: '\t' });
|
||||
|
||||
await execa('npm', ['install'], { cwd: targetPath });
|
||||
const packageManager = getPackageManager();
|
||||
|
||||
await execa(packageManager, ['install'], { cwd: targetPath });
|
||||
|
||||
spinner.succeed(chalk.bold('Done'));
|
||||
|
||||
log(getDoneMessage(type, targetDir, targetPath));
|
||||
log(getDoneMessage(type, targetDir, targetPath, packageManager));
|
||||
}
|
||||
|
||||
function getPackageManifest(name: string, options: ExtensionOptions, deps: Record<string, string>) {
|
||||
@@ -162,15 +167,15 @@ function getPackageManifest(name: string, options: ExtensionOptions, deps: Recor
|
||||
};
|
||||
}
|
||||
|
||||
function getDoneMessage(type: ExtensionPackageType, targetDir: string, targetPath: string) {
|
||||
function getDoneMessage(type: ExtensionPackageType, targetDir: string, targetPath: string, packageManager: string) {
|
||||
return `
|
||||
Your ${type} extension has been created at ${chalk.green(targetPath)}
|
||||
|
||||
To start developing, run:
|
||||
${chalk.blue('cd')} ${targetDir}
|
||||
${chalk.blue('npm run')} dev
|
||||
${chalk.blue(`${packageManager} run`)} dev
|
||||
|
||||
and then to build for production, run:
|
||||
${chalk.blue('npm run')} build
|
||||
${chalk.blue(`${packageManager} run`)} build
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import { afterEach, expect, test } from 'vitest';
|
||||
import getPackageManagerAgent from './get-package-manager-agent';
|
||||
|
||||
const envCopy = { ...process.env };
|
||||
|
||||
afterEach(() => {
|
||||
process.env = envCopy;
|
||||
});
|
||||
|
||||
test('Returns null if user agent cannot be extracted from env', () => {
|
||||
delete process.env.npm_config_user_agent;
|
||||
expect(getPackageManagerAgent()).toBe(null);
|
||||
});
|
||||
|
||||
test('Returns information object from parsed user agent', () => {
|
||||
process.env.npm_config_user_agent = 'pnpm/7.16.0 npm/? node/v18.12.1 darwin arm64';
|
||||
|
||||
expect(getPackageManagerAgent()).toStrictEqual({
|
||||
node: 'v18.12.1',
|
||||
npm: '?',
|
||||
os: 'darwin (arm64)',
|
||||
pnpm: '7.16.0',
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Extract the npm user agent from the npm_config_user_agent environment variable string
|
||||
*/
|
||||
export default function getPackageManagerAgent(): Record<string, string> | null {
|
||||
const userAgent = process.env.npm_config_user_agent;
|
||||
|
||||
if (!userAgent) return null;
|
||||
|
||||
const values = userAgent.split(' ');
|
||||
const fields = values.filter((field) => field.includes('/'));
|
||||
const [platform, arch] = values.filter((field) => !field.includes('/'));
|
||||
|
||||
return Object.fromEntries(fields.map((field) => field.split('/')).concat([['os', `${platform} (${arch})`]]));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { vi, afterEach, expect, test } from 'vitest';
|
||||
import getPackageManagerAgent from './get-package-manager-agent';
|
||||
import getPackageManager from './get-package-manager';
|
||||
|
||||
vi.mock('./get-package-manager-agent');
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('Returns npm is agent data is unavailable', () => {
|
||||
vi.mocked(getPackageManagerAgent).mockReturnValueOnce(null);
|
||||
expect(getPackageManager()).toBe('npm');
|
||||
});
|
||||
|
||||
test('Returns pnpm if pnpm exists in agent and is not ?', () => {
|
||||
vi.mocked(getPackageManagerAgent).mockReturnValueOnce({
|
||||
node: 'v18.12.1',
|
||||
npm: '?',
|
||||
os: 'darwin (arm64)',
|
||||
pnpm: '7.16.0',
|
||||
});
|
||||
|
||||
expect(getPackageManager()).toBe('pnpm');
|
||||
});
|
||||
|
||||
test('Returns yarn if yarn exists in agent and is not ?', () => {
|
||||
vi.mocked(getPackageManagerAgent).mockReturnValueOnce({
|
||||
node: 'v18.12.1',
|
||||
npm: '?',
|
||||
os: 'darwin (arm64)',
|
||||
yarn: '2',
|
||||
});
|
||||
|
||||
expect(getPackageManager()).toBe('yarn');
|
||||
});
|
||||
|
||||
test('Returns npm is neither pnpm or yarn exist', () => {
|
||||
vi.mocked(getPackageManagerAgent).mockReturnValueOnce({
|
||||
node: 'v18.12.1',
|
||||
npm: '8.19.2',
|
||||
os: 'darwin (arm64)',
|
||||
});
|
||||
|
||||
expect(getPackageManager()).toBe('npm');
|
||||
});
|
||||
15
packages/extensions-sdk/src/cli/utils/get-package-manager.ts
Normal file
15
packages/extensions-sdk/src/cli/utils/get-package-manager.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import getPackageManagerAgent from './get-package-manager-agent';
|
||||
|
||||
/**
|
||||
* Determine whether to use pnpm, yarn, or npm based on the parsed package manager agent info
|
||||
*/
|
||||
export default function getPackageManager(): string {
|
||||
const agent = getPackageManagerAgent();
|
||||
|
||||
if (agent !== null) {
|
||||
if ('pnpm' in agent && agent.pnpm !== '?') return 'pnpm';
|
||||
if ('yarn' in agent && agent.yarn !== '?') return 'yarn';
|
||||
}
|
||||
|
||||
return 'npm';
|
||||
}
|
||||
4
pnpm-lock.yaml
generated
4
pnpm-lock.yaml
generated
@@ -761,6 +761,7 @@ importers:
|
||||
'@rollup/plugin-virtual': 3.0.1
|
||||
'@types/fs-extra': 9.0.13
|
||||
'@types/inquirer': 8.2.1
|
||||
'@vitest/coverage-c8': 0.25.2
|
||||
'@vue/compiler-sfc': 3.2.45
|
||||
chalk: 4.1.1
|
||||
commander: 9.4.1
|
||||
@@ -775,6 +776,7 @@ importers:
|
||||
rollup-plugin-typescript2: 0.34.1
|
||||
rollup-plugin-vue: 6.0.0
|
||||
typescript: 4.9.3
|
||||
vitest: 0.25.2
|
||||
dependencies:
|
||||
'@directus/shared': link:../shared
|
||||
'@rollup/plugin-commonjs': 23.0.2_rollup@3.3.0
|
||||
@@ -797,9 +799,11 @@ importers:
|
||||
devDependencies:
|
||||
'@types/fs-extra': 9.0.13
|
||||
'@types/inquirer': 8.2.1
|
||||
'@vitest/coverage-c8': 0.25.2
|
||||
npm-run-all: 4.1.5
|
||||
rimraf: 3.0.2
|
||||
typescript: 4.9.3
|
||||
vitest: 0.25.2
|
||||
|
||||
packages/schema:
|
||||
specifiers:
|
||||
|
||||
Reference in New Issue
Block a user