diff --git a/graph/ui-project-details/src/lib/target-configuration-details-header/target-configuration-details-header.tsx b/graph/ui-project-details/src/lib/target-configuration-details-header/target-configuration-details-header.tsx index 5336cefc7bece..6005c20c6ab57 100644 --- a/graph/ui-project-details/src/lib/target-configuration-details-header/target-configuration-details-header.tsx +++ b/graph/ui-project-details/src/lib/target-configuration-details-header/target-configuration-details-header.tsx @@ -14,6 +14,8 @@ import { Pill } from '../pill'; import { TargetTechnologies } from '../target-technologies/target-technologies'; import { SourceInfo } from '../source-info/source-info'; import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard'; +import { getDisplayHeaderFromTargetConfiguration } from '../utils/get-display-header-from-target-configuration'; +import { TargetExecutor } from '../target-executor/target-executor'; export interface TargetConfigurationDetailsHeaderProps { isCollasped: boolean; @@ -52,10 +54,8 @@ export const TargetConfigurationDetailsHeader = ({ isCollasped = false; } - const singleCommand = - targetConfiguration.executor === 'nx:run-commands' - ? targetConfiguration.command ?? targetConfiguration.options?.command - : null; + const { command, commands, script, executor } = + getDisplayHeaderFromTargetConfiguration(targetConfiguration); return (
- {singleCommand ? singleCommand : targetConfiguration.executor} +

)} {targetName === 'nx-release-publish' && ( diff --git a/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx b/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx index 876b11af56639..47192d8263c5e 100644 --- a/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx +++ b/graph/ui-project-details/src/lib/target-configuration-details/target-configuration-details.tsx @@ -3,21 +3,20 @@ import type { TargetConfiguration } from '@nx/devkit'; import { JsonCodeBlock } from '@nx/graph/ui-code-block'; -import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; +import { useCallback, useContext, useEffect, useState } from 'react'; import { SourceInfo } from '../source-info/source-info'; import { FadingCollapsible } from './fading-collapsible'; import { TargetConfigurationProperty } from './target-configuration-property'; import { selectSourceInfo } from './target-configuration-details.util'; import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard'; -import { - ExternalLink, - PropertyInfoTooltip, - Tooltip, -} from '@nx/graph/ui-tooltips'; +import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips'; import { TooltipTriggerText } from './tooltip-trigger-text'; import { Pill } from '../pill'; import { TargetConfigurationDetailsHeader } from '../target-configuration-details-header/target-configuration-details-header'; import { ExpandedTargetsContext } from '@nx/graph/shared'; +import { getDisplayHeaderFromTargetConfiguration } from '../utils/get-display-header-from-target-configuration'; +import { TargetExecutor } from '../target-executor/target-executor'; +import { TargetExecutorTitle } from '../target-executor/target-executor-title'; interface TargetConfigurationDetailsProps { projectName: string; @@ -71,36 +70,8 @@ export default function TargetConfigurationDetails({ } }, [expandedTargets, targetName, collapsable]); - let executorLink: string | null = null; - - // TODO: Handle this better because this will not work with labs - if (targetConfiguration.executor?.startsWith('@nx/')) { - const packageName = targetConfiguration.executor - .split('/')[1] - .split(':')[0]; - const executorName = targetConfiguration.executor - .split('/')[1] - .split(':')[1]; - executorLink = `https://nx.dev/nx-api/${packageName}/executors/${executorName}`; - } else if (targetConfiguration.executor === 'nx:run-commands') { - executorLink = `https://nx.dev/nx-api/nx/executors/run-commands`; - } else if (targetConfiguration.executor === 'nx:run-script') { - executorLink = `https://nx.dev/nx-api/nx/executors/run-script`; - } - - const singleCommand = - targetConfiguration.executor === 'nx:run-commands' - ? targetConfiguration.command ?? targetConfiguration.options?.command - : null; - const options = useMemo(() => { - if (singleCommand) { - const { command, ...rest } = targetConfiguration.options; - return rest; - } else { - return targetConfiguration.options; - } - }, [targetConfiguration.options, singleCommand]); - + const { link, options, script, ...displayHeader } = + getDisplayHeaderFromTargetConfiguration(targetConfiguration); const configurations = targetConfiguration.configurations; const shouldRenderOptions = @@ -132,48 +103,30 @@ export default function TargetConfigurationDetails({

- {singleCommand ? ( - - Command - - - handleCopyClick(`"command": "${singleCommand}"`) - } - /> - - - ) : ( - ) as any} - > - - Executor - - - )} +

- {executorLink ? ( - - - - ) : singleCommand ? ( - singleCommand - ) : ( - targetConfiguration.executor - )} +

+ {script && ( +
+

+ +

+

+ +

+
+ )} + {targetConfiguration.inputs && (

diff --git a/graph/ui-project-details/src/lib/target-executor/target-executor-title.stories.tsx b/graph/ui-project-details/src/lib/target-executor/target-executor-title.stories.tsx new file mode 100644 index 0000000000000..abc8761879de0 --- /dev/null +++ b/graph/ui-project-details/src/lib/target-executor/target-executor-title.stories.tsx @@ -0,0 +1,32 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { TargetExecutorTitle } from './target-executor-title'; + +const meta: Meta = { + component: TargetExecutorTitle, + title: 'TargetExecutorTitle', +}; +export default meta; + +type Story = StoryObj; + +export const Command: Story = { + args: { + command: 'nx run my-app:build', + }, +}; + +export const Commands: Story = { + args: { + commands: ['nx run my-app:build', 'nx run my-app:test'], + }, +}; + +export const Script: Story = { + args: { + script: 'nx run my-app:build', + }, +}; + +export const Executor: Story = { + args: {}, +}; diff --git a/graph/ui-project-details/src/lib/target-executor/target-executor-title.tsx b/graph/ui-project-details/src/lib/target-executor/target-executor-title.tsx new file mode 100644 index 0000000000000..75ec44e231a89 --- /dev/null +++ b/graph/ui-project-details/src/lib/target-executor/target-executor-title.tsx @@ -0,0 +1,64 @@ +import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips'; +import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard'; +import { TooltipTriggerText } from '../target-configuration-details/tooltip-trigger-text'; + +export function TargetExecutorTitle({ + commands, + command, + script, + handleCopyClick, +}: { + handleCopyClick: (copyText: string) => void; + commands?: string[]; + command?: string; + script?: string; +}) { + if (commands && commands.length) { + return ( + + Commands + + + handleCopyClick( + `"commands": [${commands.map((c) => `"${c}"`).join(', ')}]` + ) + } + /> + + + ); + } + if (command) { + return ( + + Command + + handleCopyClick(`"command": "${command}"`)} + /> + + + ); + } + if (script) { + return ( + + Script + + handleCopyClick(script)} /> + + + ); + } + return ( + ) as any} + > + + Executor + + + ); +} diff --git a/graph/ui-project-details/src/lib/target-executor/target-executor.stories.tsx b/graph/ui-project-details/src/lib/target-executor/target-executor.stories.tsx new file mode 100644 index 0000000000000..4d5b0f5786774 --- /dev/null +++ b/graph/ui-project-details/src/lib/target-executor/target-executor.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { TargetExecutor } from './target-executor'; + +const meta: Meta = { + component: TargetExecutor, + title: 'TargetExecutor', +}; +export default meta; + +type Story = StoryObj; + +export const Command: Story = { + args: { + command: 'nx run my-app:build', + }, +}; + +export const Commands: Story = { + args: { + commands: ['nx run my-app:build', 'nx run my-app:test'], + }, +}; + +export const Script: Story = { + args: { + script: 'nx run my-app:build', + }, +}; + +export const Executor: Story = { + args: { + executor: 'nx run my-app:build', + }, +}; diff --git a/graph/ui-project-details/src/lib/target-executor/target-executor.tsx b/graph/ui-project-details/src/lib/target-executor/target-executor.tsx new file mode 100644 index 0000000000000..af5aa5952fa57 --- /dev/null +++ b/graph/ui-project-details/src/lib/target-executor/target-executor.tsx @@ -0,0 +1,49 @@ +import { ExternalLink } from '@nx/graph/ui-tooltips'; + +export interface TargetExecutorProps { + command?: string; + commands?: string[]; + script?: string; + executor?: string; + isCompact?: boolean; + link?: string; +} + +export function TargetExecutor({ + command, + commands, + script, + executor, + isCompact, + link, +}: TargetExecutorProps) { + if (commands) { + if (isCompact) { + return link ? ( + + {commands.length === 1 ? commands[0] : executor} + + ) : commands.length === 1 ? ( + commands[0] + ) : ( + executor + ); + } + return ( +
    + {commands?.map((c) => + c ? ( +
  • {link ? {c} : c}
  • + ) : null + )} +
+ ); + } + + const displayText = command ?? script ?? executor ?? ''; + return link ? ( + {displayText} + ) : ( + displayText + ); +} diff --git a/graph/ui-project-details/src/lib/utils/get-display-header-from-target-configuration.ts b/graph/ui-project-details/src/lib/utils/get-display-header-from-target-configuration.ts new file mode 100644 index 0000000000000..94bdd57e4d8cd --- /dev/null +++ b/graph/ui-project-details/src/lib/utils/get-display-header-from-target-configuration.ts @@ -0,0 +1,56 @@ +/* eslint-disable @nx/enforce-module-boundaries */ +// nx-ignore-next-line +import type { TargetConfiguration } from '@nx/devkit'; + +export function getDisplayHeaderFromTargetConfiguration( + targetConfiguration: TargetConfiguration +): { + link: string | undefined; + options: Record; + command?: string; + commands?: string[]; + script?: string; + executor?: string; +} { + let link: string | undefined; + let displayText: { + command?: string; + commands?: string[]; + script?: string; + executor?: string; + } = { + executor: targetConfiguration.executor, + }; + let options = targetConfiguration.options; + // TODO: Handle this better because this will not work with labs + if (targetConfiguration.executor?.startsWith('@nx/')) { + const packageName = targetConfiguration.executor + .split('/')[1] + .split(':')[0]; + const executorName = targetConfiguration.executor + .split('/')[1] + .split(':')[1]; + link = `https://nx.dev/nx-api/${packageName}/executors/${executorName}`; + } else if (targetConfiguration.executor === 'nx:run-commands') { + link = `https://nx.dev/nx-api/nx/executors/run-commands`; + displayText.command = + targetConfiguration.command ?? targetConfiguration.options?.command; + displayText.commands = targetConfiguration.options?.commands?.map( + (c: { command: string }) => c.command ?? c + ); + const { command, commands, ...rest } = targetConfiguration.options; + options = rest; + } else if (targetConfiguration.executor === 'nx:run-script') { + link = `https://nx.dev/nx-api/nx/executors/run-script`; + displayText.command = targetConfiguration.metadata?.runCommand; + displayText.script = targetConfiguration.metadata?.scriptContent; + const { script, ...rest } = targetConfiguration.options; + options = rest; + } + + return { + ...displayText, + link, + options, + }; +} diff --git a/graph/ui-tooltips/src/lib/external-link.tsx b/graph/ui-tooltips/src/lib/external-link.tsx index ebc01e5e412eb..13f39430b508f 100644 --- a/graph/ui-tooltips/src/lib/external-link.tsx +++ b/graph/ui-tooltips/src/lib/external-link.tsx @@ -1,11 +1,11 @@ import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'; export function ExternalLink({ - text, + children, href, title, }: { - text: string; + children?: React.ReactNode; href: string; title?: string; }) { @@ -13,10 +13,11 @@ export function ExternalLink({ - {text} + {children} ); } diff --git a/graph/ui-tooltips/src/lib/property-info-tooltip.tsx b/graph/ui-tooltips/src/lib/property-info-tooltip.tsx index 4412af6f4f373..ecc8882c85c30 100644 --- a/graph/ui-tooltips/src/lib/property-info-tooltip.tsx +++ b/graph/ui-tooltips/src/lib/property-info-tooltip.tsx @@ -106,13 +106,10 @@ export function PropertyInfoTooltip({ type }: PropertyInfoTooltipProps) { {propertyInfo.docsUrl ? (

- + + {propertyInfo.docsLinkText ?? + `Learn more about ${propertyInfo.heading}`} +

) : null} diff --git a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx b/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx index dea15ce7d37d3..b7534c68cdd07 100644 --- a/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx +++ b/graph/ui-tooltips/src/lib/sourcemap-info-tooltip.tsx @@ -30,10 +30,9 @@ export function SourcemapInfoToolTip({ {isTarget ? 'Created' : 'Set'} by: {docsUrlSlug ? ( - + + {plugin} + ) : ( `${plugin}` )} @@ -46,7 +45,7 @@ export function SourcemapInfoToolTip({ ); return ( -
+

- + + Learn more about how projects are configured +

)} diff --git a/packages/nx/src/config/workspace-json-project-json.ts b/packages/nx/src/config/workspace-json-project-json.ts index 83b3ea352ed86..d2ef9a8987425 100644 --- a/packages/nx/src/config/workspace-json-project-json.ts +++ b/packages/nx/src/config/workspace-json-project-json.ts @@ -124,6 +124,7 @@ export interface ProjectMetadata { } export interface TargetMetadata { + [k: string]: any; description?: string; technologies?: string[]; } diff --git a/packages/nx/src/plugins/package-json-workspaces/create-nodes.spec.ts b/packages/nx/src/plugins/package-json-workspaces/create-nodes.spec.ts index dc3aa60310b61..42ea4e7f4c504 100644 --- a/packages/nx/src/plugins/package-json-workspaces/create-nodes.spec.ts +++ b/packages/nx/src/plugins/package-json-workspaces/create-nodes.spec.ts @@ -48,6 +48,10 @@ describe('nx package.json workspaces plugin', () => { "targets": { "echo": { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run echo", + "scriptContent": "echo root project", + }, "options": { "script": "echo", }, @@ -83,6 +87,10 @@ describe('nx package.json workspaces plugin', () => { }, "test": { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "jest", + }, "options": { "script": "test", }, @@ -111,6 +119,10 @@ describe('nx package.json workspaces plugin', () => { "targets": { "build": { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run build", + "scriptContent": "tsc", + }, "options": { "script": "build", }, @@ -127,6 +139,10 @@ describe('nx package.json workspaces plugin', () => { }, "test": { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "jest", + }, "options": { "script": "test", }, diff --git a/packages/nx/src/plugins/project-json/build-nodes/package-json-next-to-project-json.spec.ts b/packages/nx/src/plugins/project-json/build-nodes/package-json-next-to-project-json.spec.ts index cc55fa3f7f968..76cbfaf967c6d 100644 --- a/packages/nx/src/plugins/project-json/build-nodes/package-json-next-to-project-json.spec.ts +++ b/packages/nx/src/plugins/project-json/build-nodes/package-json-next-to-project-json.spec.ts @@ -58,6 +58,10 @@ describe('nx project.json plugin', () => { }, "test": { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "jest", + }, "options": { "script": "test", }, diff --git a/packages/nx/src/plugins/target-defaults/target-defaults-plugin.spec.ts b/packages/nx/src/plugins/target-defaults/target-defaults-plugin.spec.ts index 8dd59a38c9e37..4f000fe8833dc 100644 --- a/packages/nx/src/plugins/target-defaults/target-defaults-plugin.spec.ts +++ b/packages/nx/src/plugins/target-defaults/target-defaults-plugin.spec.ts @@ -78,6 +78,7 @@ describe('target-defaults plugin', () => { "^build", ], "executor": "nx:run-commands", + "metadata": {}, }, }, }, @@ -121,6 +122,10 @@ describe('target-defaults plugin', () => { "test": { "command": "jest", "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "nx affected:test", + }, "options": { "script": "test", }, @@ -169,6 +174,10 @@ describe('target-defaults plugin', () => { "test": { "command": "jest", "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "nx affected:test", + }, "options": { "script": "test", }, @@ -380,12 +389,14 @@ describe('target-defaults plugin', () => { "targets": { "echo": { "executor": "nx:run-commands", + "metadata": {}, "options": { "cwd": "{projectRoot}", }, }, "echo2": { "executor": "nx:run-commands", + "metadata": {}, "options": { "cwd": "{projectRoot}", }, @@ -445,12 +456,14 @@ describe('target-defaults plugin', () => { "targets": { "echo": { "executor": "nx:run-commands", + "metadata": {}, "options": { "cwd": "{projectRoot}", }, }, "echo2": { "executor": "nx:run-commands", + "metadata": {}, "options": { "cwd": "{projectRoot}", }, @@ -483,6 +496,7 @@ describe('target-defaults plugin', () => { expect(result).toMatchInlineSnapshot(` { "command": "echo hi", + "metadata": {}, } `); }); @@ -504,6 +518,7 @@ describe('target-defaults plugin', () => { expect(result).toMatchInlineSnapshot(` { "executor": "nx:run-commands", + "metadata": {}, "options": { "command": "echo hi", }, @@ -524,6 +539,7 @@ describe('target-defaults plugin', () => { ).toMatchInlineSnapshot(` { "executor": "nx:run-script", + "metadata": {}, "options": { "script": "build", }, diff --git a/packages/nx/src/plugins/target-defaults/target-defaults-plugin.ts b/packages/nx/src/plugins/target-defaults/target-defaults-plugin.ts index f383e2c477fd8..b98770b9b0668 100644 --- a/packages/nx/src/plugins/target-defaults/target-defaults-plugin.ts +++ b/packages/nx/src/plugins/target-defaults/target-defaults-plugin.ts @@ -167,10 +167,15 @@ export function getTargetInfo( ...packageJsonTarget?.options, ...projectJsonTarget?.options, }; + const metadata = { + ...packageJsonTarget?.metadata, + ...projectJsonTarget?.metadata, + }; if (projectJsonTarget?.command) { return { command: projectJsonTarget?.command, + metadata, }; } @@ -181,6 +186,7 @@ export function getTargetInfo( options: { command: targetOptions?.command, }, + metadata, }; } else if (targetOptions?.commands) { return { @@ -188,10 +194,12 @@ export function getTargetInfo( options: { commands: targetOptions.commands, }, + metadata, }; } return { executor: 'nx:run-commands', + metadata, }; } @@ -201,6 +209,7 @@ export function getTargetInfo( options: { script: targetOptions?.script ?? target, }, + metadata, }; } diff --git a/packages/nx/src/utils/package-json.spec.ts b/packages/nx/src/utils/package-json.spec.ts index 7503762451d5d..5508fd2a42c97 100644 --- a/packages/nx/src/utils/package-json.spec.ts +++ b/packages/nx/src/utils/package-json.spec.ts @@ -29,23 +29,35 @@ describe('readTargetsFromPackageJson', () => { options: { script: 'build', }, + metadata: { + runCommand: 'npm run build', + scriptContent: 'echo 1', + }, }; it('should read targets from project.json and package.json', () => { const result = readTargetsFromPackageJson(packageJson); - expect(result).toEqual({ - build: { - executor: 'nx:run-script', - options: { - script: 'build', + expect(result).toMatchInlineSnapshot(` + { + "build": { + "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run build", + "scriptContent": "echo 1", + }, + "options": { + "script": "build", + }, }, - }, - 'nx-release-publish': { - dependsOn: ['^nx-release-publish'], - executor: '@nx/js:release-publish', - options: {}, - }, - }); + "nx-release-publish": { + "dependsOn": [ + "^nx-release-publish", + ], + "executor": "@nx/js:release-publish", + "options": {}, + }, + } + `); }); it('should contain extended options from nx property in package.json', () => { @@ -86,17 +98,27 @@ describe('readTargetsFromPackageJson', () => { }, }); - expect(result).toEqual({ - test: { - executor: 'nx:run-script', - options: { script: 'test' }, - }, - 'nx-release-publish': { - dependsOn: ['^nx-release-publish'], - executor: '@nx/js:release-publish', - options: {}, - }, - }); + expect(result).toMatchInlineSnapshot(` + { + "nx-release-publish": { + "dependsOn": [ + "^nx-release-publish", + ], + "executor": "@nx/js:release-publish", + "options": {}, + }, + "test": { + "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run test", + "scriptContent": "echo testing", + }, + "options": { + "script": "test", + }, + }, + } + `); }); it('should extend script based targets if matching config', () => { @@ -117,6 +139,10 @@ describe('readTargetsFromPackageJson', () => { expect(result.build).toMatchInlineSnapshot(` { "executor": "nx:run-script", + "metadata": { + "runCommand": "npm run build", + "scriptContent": "echo 1", + }, "options": { "script": "build", }, diff --git a/packages/nx/src/utils/package-json.ts b/packages/nx/src/utils/package-json.ts index 0b7de85bf4b99..14f4e2fdea65e 100644 --- a/packages/nx/src/utils/package-json.ts +++ b/packages/nx/src/utils/package-json.ts @@ -7,6 +7,7 @@ import { import { mergeTargetConfigurations } from '../project-graph/utils/project-configuration-utils'; import { readJsonFile } from './fileutils'; import { getNxRequirePaths } from './installation-directory'; +import { getPackageManagerCommand } from './package-manager'; export interface NxProjectPackageJsonConfiguration { implicitDependencies?: string[]; @@ -115,12 +116,20 @@ export function readNxMigrateConfig( }; } -export function buildTargetFromScript(script: string): TargetConfiguration { +export function buildTargetFromScript( + script: string, + scripts: Record = {} +): TargetConfiguration { + const packageManagerCommand = getPackageManagerCommand(); return { executor: 'nx:run-script', options: { script, }, + metadata: { + scriptContent: scripts[script], + runCommand: packageManagerCommand.run(script), + }, }; } @@ -130,7 +139,7 @@ export function readTargetsFromPackageJson(packageJson: PackageJson) { const includedScripts = nx?.includedScripts || Object.keys(scripts ?? {}); // for (const script of includedScripts) { - res[script] = buildTargetFromScript(script); + res[script] = buildTargetFromScript(script, scripts); } for (const targetName in nx?.targets) { res[targetName] = mergeTargetConfigurations( diff --git a/packages/nx/src/utils/package-manager.ts b/packages/nx/src/utils/package-manager.ts index b6668acc07e76..2fe5f28ef4776 100644 --- a/packages/nx/src/utils/package-manager.ts +++ b/packages/nx/src/utils/package-manager.ts @@ -26,7 +26,7 @@ export interface PackageManagerCommands { exec: string; dlx: string; list: string; - run: (script: string, args: string) => string; + run: (script: string, args?: string) => string; getRegistryUrl: string; } @@ -100,7 +100,8 @@ export function getPackageManagerCommand( rm: 'yarn remove', exec: 'yarn', dlx: useBerry ? 'yarn dlx' : 'yarn', - run: (script: string, args: string) => `yarn ${script} ${args}`, + run: (script: string, args?: string) => + `yarn ${script}${args ? ` ${args}` : ''}`, list: useBerry ? 'yarn info --name-only' : 'yarn list', getRegistryUrl: useBerry ? 'yarn config get npmRegistryServer' @@ -122,10 +123,14 @@ export function getPackageManagerCommand( rm: 'pnpm rm', exec: modernPnpm ? 'pnpm exec' : 'pnpx', dlx: modernPnpm ? 'pnpm dlx' : 'pnpx', - run: (script: string, args: string) => - includeDoubleDashBeforeArgs - ? `pnpm run ${script} -- ${args}` - : `pnpm run ${script} ${args}`, + run: (script: string, args?: string) => + `pnpm run ${script}${ + args + ? includeDoubleDashBeforeArgs + ? ' -- ' + args + : ` ${args}` + : '' + }`, list: 'pnpm ls --depth 100', getRegistryUrl: 'pnpm config get registry', }; @@ -143,7 +148,8 @@ export function getPackageManagerCommand( rm: 'npm rm', exec: 'npx', dlx: 'npx', - run: (script: string, args: string) => `npm run ${script} -- ${args}`, + run: (script: string, args?: string) => + `npm run ${script}${args ? ' -- ' + args : ''}`, list: 'npm ls', getRegistryUrl: 'npm config get registry', };