feat(graph): show script content in header (#23257)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR -->  <img width="1023" alt="Screenshot 2024-05-08 at 5 53 06 PM" src="https://github.com/nrwl/nx/assets/16211801/cb9161bd-fc4a-4965-89f7-09ce8d72226e"> <img width="585" alt="Screenshot 2024-05-08 at 5 52 51 PM" src="https://github.com/nrwl/nx/assets/16211801/760ebe19-1c29-4fad-ba9d-174b8303a362"> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
992ae85192
commit
08ef0e4bde
@ -14,6 +14,8 @@ import { Pill } from '../pill';
|
|||||||
import { TargetTechnologies } from '../target-technologies/target-technologies';
|
import { TargetTechnologies } from '../target-technologies/target-technologies';
|
||||||
import { SourceInfo } from '../source-info/source-info';
|
import { SourceInfo } from '../source-info/source-info';
|
||||||
import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard';
|
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 {
|
export interface TargetConfigurationDetailsHeaderProps {
|
||||||
isCollasped: boolean;
|
isCollasped: boolean;
|
||||||
@ -52,10 +54,8 @@ export const TargetConfigurationDetailsHeader = ({
|
|||||||
isCollasped = false;
|
isCollasped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const singleCommand =
|
const { command, commands, script, executor } =
|
||||||
targetConfiguration.executor === 'nx:run-commands'
|
getDisplayHeaderFromTargetConfiguration(targetConfiguration);
|
||||||
? targetConfiguration.command ?? targetConfiguration.options?.command
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header
|
<header
|
||||||
@ -86,7 +86,13 @@ export const TargetConfigurationDetailsHeader = ({
|
|||||||
{isCollasped &&
|
{isCollasped &&
|
||||||
targetConfiguration?.executor !== '@nx/js:release-publish' && (
|
targetConfiguration?.executor !== '@nx/js:release-publish' && (
|
||||||
<p className="min-w-0 flex-1 truncate text-sm text-slate-400">
|
<p className="min-w-0 flex-1 truncate text-sm text-slate-400">
|
||||||
{singleCommand ? singleCommand : targetConfiguration.executor}
|
<TargetExecutor
|
||||||
|
command={command}
|
||||||
|
commands={commands}
|
||||||
|
script={script}
|
||||||
|
executor={executor}
|
||||||
|
isCompact={true}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{targetName === 'nx-release-publish' && (
|
{targetName === 'nx-release-publish' && (
|
||||||
|
|||||||
@ -3,21 +3,20 @@
|
|||||||
import type { TargetConfiguration } from '@nx/devkit';
|
import type { TargetConfiguration } from '@nx/devkit';
|
||||||
|
|
||||||
import { JsonCodeBlock } from '@nx/graph/ui-code-block';
|
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 { SourceInfo } from '../source-info/source-info';
|
||||||
import { FadingCollapsible } from './fading-collapsible';
|
import { FadingCollapsible } from './fading-collapsible';
|
||||||
import { TargetConfigurationProperty } from './target-configuration-property';
|
import { TargetConfigurationProperty } from './target-configuration-property';
|
||||||
import { selectSourceInfo } from './target-configuration-details.util';
|
import { selectSourceInfo } from './target-configuration-details.util';
|
||||||
import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard';
|
import { CopyToClipboard } from '../copy-to-clipboard/copy-to-clipboard';
|
||||||
import {
|
import { PropertyInfoTooltip, Tooltip } from '@nx/graph/ui-tooltips';
|
||||||
ExternalLink,
|
|
||||||
PropertyInfoTooltip,
|
|
||||||
Tooltip,
|
|
||||||
} from '@nx/graph/ui-tooltips';
|
|
||||||
import { TooltipTriggerText } from './tooltip-trigger-text';
|
import { TooltipTriggerText } from './tooltip-trigger-text';
|
||||||
import { Pill } from '../pill';
|
import { Pill } from '../pill';
|
||||||
import { TargetConfigurationDetailsHeader } from '../target-configuration-details-header/target-configuration-details-header';
|
import { TargetConfigurationDetailsHeader } from '../target-configuration-details-header/target-configuration-details-header';
|
||||||
import { ExpandedTargetsContext } from '@nx/graph/shared';
|
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 {
|
interface TargetConfigurationDetailsProps {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
@ -71,36 +70,8 @@ export default function TargetConfigurationDetails({
|
|||||||
}
|
}
|
||||||
}, [expandedTargets, targetName, collapsable]);
|
}, [expandedTargets, targetName, collapsable]);
|
||||||
|
|
||||||
let executorLink: string | null = null;
|
const { link, options, script, ...displayHeader } =
|
||||||
|
getDisplayHeaderFromTargetConfiguration(targetConfiguration);
|
||||||
// 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 configurations = targetConfiguration.configurations;
|
const configurations = targetConfiguration.configurations;
|
||||||
|
|
||||||
const shouldRenderOptions =
|
const shouldRenderOptions =
|
||||||
@ -132,48 +103,30 @@ export default function TargetConfigurationDetails({
|
|||||||
<div className="p-4 text-base">
|
<div className="p-4 text-base">
|
||||||
<div className="group mb-4">
|
<div className="group mb-4">
|
||||||
<h4 className="mb-4">
|
<h4 className="mb-4">
|
||||||
{singleCommand ? (
|
<TargetExecutorTitle
|
||||||
<span className="font-medium">
|
{...displayHeader}
|
||||||
Command
|
handleCopyClick={handleCopyClick}
|
||||||
<span className="mb-1 ml-2 hidden group-hover:inline">
|
/>
|
||||||
<CopyToClipboard
|
|
||||||
onCopy={() =>
|
|
||||||
handleCopyClick(`"command": "${singleCommand}"`)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<Tooltip
|
|
||||||
openAction="hover"
|
|
||||||
content={(<PropertyInfoTooltip type="executors" />) as any}
|
|
||||||
>
|
|
||||||
<span className="font-medium">
|
|
||||||
<TooltipTriggerText>Executor</TooltipTriggerText>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</h4>
|
</h4>
|
||||||
<p className="pl-5 font-mono">
|
<p className="pl-5 font-mono">
|
||||||
{executorLink ? (
|
<TargetExecutor {...displayHeader} link={link} />
|
||||||
<span>
|
|
||||||
<ExternalLink
|
|
||||||
href={executorLink ?? 'https://nx.dev/nx-api'}
|
|
||||||
text={
|
|
||||||
singleCommand
|
|
||||||
? singleCommand
|
|
||||||
: targetConfiguration.executor
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
) : singleCommand ? (
|
|
||||||
singleCommand
|
|
||||||
) : (
|
|
||||||
targetConfiguration.executor
|
|
||||||
)}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{script && (
|
||||||
|
<div className="group mb-4">
|
||||||
|
<h4 className="mb-4">
|
||||||
|
<TargetExecutorTitle
|
||||||
|
script={script}
|
||||||
|
handleCopyClick={handleCopyClick}
|
||||||
|
/>
|
||||||
|
</h4>
|
||||||
|
<p className="pl-5 font-mono">
|
||||||
|
<TargetExecutor script={script} link={link} />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{targetConfiguration.inputs && (
|
{targetConfiguration.inputs && (
|
||||||
<div className="group">
|
<div className="group">
|
||||||
<h4 className="mb-4">
|
<h4 className="mb-4">
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { TargetExecutorTitle } from './target-executor-title';
|
||||||
|
|
||||||
|
const meta: Meta<typeof TargetExecutorTitle> = {
|
||||||
|
component: TargetExecutorTitle,
|
||||||
|
title: 'TargetExecutorTitle',
|
||||||
|
};
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof TargetExecutorTitle>;
|
||||||
|
|
||||||
|
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: {},
|
||||||
|
};
|
||||||
@ -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 (
|
||||||
|
<span className="font-medium">
|
||||||
|
Commands
|
||||||
|
<span className="mb-1 ml-2 hidden group-hover:inline">
|
||||||
|
<CopyToClipboard
|
||||||
|
onCopy={() =>
|
||||||
|
handleCopyClick(
|
||||||
|
`"commands": [${commands.map((c) => `"${c}"`).join(', ')}]`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (command) {
|
||||||
|
return (
|
||||||
|
<span className="font-medium">
|
||||||
|
Command
|
||||||
|
<span className="mb-1 ml-2 hidden group-hover:inline">
|
||||||
|
<CopyToClipboard
|
||||||
|
onCopy={() => handleCopyClick(`"command": "${command}"`)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (script) {
|
||||||
|
return (
|
||||||
|
<span className="font-medium">
|
||||||
|
Script
|
||||||
|
<span className="mb-1 ml-2 hidden group-hover:inline">
|
||||||
|
<CopyToClipboard onCopy={() => handleCopyClick(script)} />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
openAction="hover"
|
||||||
|
content={(<PropertyInfoTooltip type="executors" />) as any}
|
||||||
|
>
|
||||||
|
<span className="font-medium">
|
||||||
|
<TooltipTriggerText>Executor</TooltipTriggerText>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { TargetExecutor } from './target-executor';
|
||||||
|
|
||||||
|
const meta: Meta<typeof TargetExecutor> = {
|
||||||
|
component: TargetExecutor,
|
||||||
|
title: 'TargetExecutor',
|
||||||
|
};
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof TargetExecutor>;
|
||||||
|
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -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 ? (
|
||||||
|
<ExternalLink href={link}>
|
||||||
|
{commands.length === 1 ? commands[0] : executor}
|
||||||
|
</ExternalLink>
|
||||||
|
) : commands.length === 1 ? (
|
||||||
|
commands[0]
|
||||||
|
) : (
|
||||||
|
executor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{commands?.map((c) =>
|
||||||
|
c ? (
|
||||||
|
<li>{link ? <ExternalLink href={link}>{c}</ExternalLink> : c}</li>
|
||||||
|
) : null
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayText = command ?? script ?? executor ?? '';
|
||||||
|
return link ? (
|
||||||
|
<ExternalLink href={link}>{displayText}</ExternalLink>
|
||||||
|
) : (
|
||||||
|
displayText
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -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<string, any>;
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline';
|
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline';
|
||||||
|
|
||||||
export function ExternalLink({
|
export function ExternalLink({
|
||||||
text,
|
children,
|
||||||
href,
|
href,
|
||||||
title,
|
title,
|
||||||
}: {
|
}: {
|
||||||
text: string;
|
children?: React.ReactNode;
|
||||||
href: string;
|
href: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
}) {
|
}) {
|
||||||
@ -13,10 +13,11 @@ export function ExternalLink({
|
|||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
title={title}
|
title={title}
|
||||||
className="text-slate-500 dark:text-slate-400 hover:underline inline-flex items-center gap-2"
|
className="gap-2 text-slate-500 hover:underline dark:text-slate-400"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{text} <ArrowTopRightOnSquareIcon className="w-4 h-4 inline" />
|
{children} <ArrowTopRightOnSquareIcon className="inline h-4 w-4" />
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,13 +106,10 @@ export function PropertyInfoTooltip({ type }: PropertyInfoTooltipProps) {
|
|||||||
{propertyInfo.docsUrl ? (
|
{propertyInfo.docsUrl ? (
|
||||||
<div className="flex py-2">
|
<div className="flex py-2">
|
||||||
<p className="flex items-center pr-4">
|
<p className="flex items-center pr-4">
|
||||||
<ExternalLink
|
<ExternalLink href={propertyInfo.docsUrl}>
|
||||||
text={
|
{propertyInfo.docsLinkText ??
|
||||||
propertyInfo.docsLinkText ??
|
`Learn more about ${propertyInfo.heading}`}
|
||||||
`Learn more about ${propertyInfo.heading}`
|
</ExternalLink>
|
||||||
}
|
|
||||||
href={propertyInfo.docsUrl}
|
|
||||||
/>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@ -30,10 +30,9 @@ export function SourcemapInfoToolTip({
|
|||||||
<span className="font-bold">{isTarget ? 'Created' : 'Set'} by:</span>
|
<span className="font-bold">{isTarget ? 'Created' : 'Set'} by:</span>
|
||||||
<span className="inline-flex grow items-center justify-between">
|
<span className="inline-flex grow items-center justify-between">
|
||||||
{docsUrlSlug ? (
|
{docsUrlSlug ? (
|
||||||
<ExternalLink
|
<ExternalLink href={`https://nx.dev/nx-api/${docsUrlSlug}`}>
|
||||||
text={plugin}
|
{plugin}
|
||||||
href={`https://nx.dev/nx-api/${docsUrlSlug}`}
|
</ExternalLink>
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
`${plugin}`
|
`${plugin}`
|
||||||
)}
|
)}
|
||||||
@ -46,7 +45,7 @@ export function SourcemapInfoToolTip({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-md text-sm text-slate-700 dark:text-slate-400 sm:max-w-full">
|
<div className="max-w-md text-sm text-slate-700 sm:max-w-full dark:text-slate-400">
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
`flex flex-col py-2 font-mono`,
|
`flex flex-col py-2 font-mono`,
|
||||||
@ -58,10 +57,9 @@ export function SourcemapInfoToolTip({
|
|||||||
{showLink && (
|
{showLink && (
|
||||||
<div className="flex py-2">
|
<div className="flex py-2">
|
||||||
<p className={`flex flex-col gap-1`}>
|
<p className={`flex flex-col gap-1`}>
|
||||||
<ExternalLink
|
<ExternalLink href="https://nx.dev/concepts/inferred-tasks">
|
||||||
text="Learn more about how projects are configured"
|
Learn more about how projects are configured
|
||||||
href="https://nx.dev/concepts/inferred-tasks"
|
</ExternalLink>
|
||||||
/>
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -124,6 +124,7 @@ export interface ProjectMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TargetMetadata {
|
export interface TargetMetadata {
|
||||||
|
[k: string]: any;
|
||||||
description?: string;
|
description?: string;
|
||||||
technologies?: string[];
|
technologies?: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,10 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
"targets": {
|
"targets": {
|
||||||
"echo": {
|
"echo": {
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run echo",
|
||||||
|
"scriptContent": "echo root project",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "echo",
|
"script": "echo",
|
||||||
},
|
},
|
||||||
@ -83,6 +87,10 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run test",
|
||||||
|
"scriptContent": "jest",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "test",
|
"script": "test",
|
||||||
},
|
},
|
||||||
@ -111,6 +119,10 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
"targets": {
|
"targets": {
|
||||||
"build": {
|
"build": {
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run build",
|
||||||
|
"scriptContent": "tsc",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "build",
|
"script": "build",
|
||||||
},
|
},
|
||||||
@ -127,6 +139,10 @@ describe('nx package.json workspaces plugin', () => {
|
|||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run test",
|
||||||
|
"scriptContent": "jest",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "test",
|
"script": "test",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -58,6 +58,10 @@ describe('nx project.json plugin', () => {
|
|||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run test",
|
||||||
|
"scriptContent": "jest",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "test",
|
"script": "test",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -78,6 +78,7 @@ describe('target-defaults plugin', () => {
|
|||||||
"^build",
|
"^build",
|
||||||
],
|
],
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -121,6 +122,10 @@ describe('target-defaults plugin', () => {
|
|||||||
"test": {
|
"test": {
|
||||||
"command": "jest",
|
"command": "jest",
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run test",
|
||||||
|
"scriptContent": "nx affected:test",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "test",
|
"script": "test",
|
||||||
},
|
},
|
||||||
@ -169,6 +174,10 @@ describe('target-defaults plugin', () => {
|
|||||||
"test": {
|
"test": {
|
||||||
"command": "jest",
|
"command": "jest",
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run test",
|
||||||
|
"scriptContent": "nx affected:test",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "test",
|
"script": "test",
|
||||||
},
|
},
|
||||||
@ -380,12 +389,14 @@ describe('target-defaults plugin', () => {
|
|||||||
"targets": {
|
"targets": {
|
||||||
"echo": {
|
"echo": {
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "{projectRoot}",
|
"cwd": "{projectRoot}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"echo2": {
|
"echo2": {
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "{projectRoot}",
|
"cwd": "{projectRoot}",
|
||||||
},
|
},
|
||||||
@ -445,12 +456,14 @@ describe('target-defaults plugin', () => {
|
|||||||
"targets": {
|
"targets": {
|
||||||
"echo": {
|
"echo": {
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "{projectRoot}",
|
"cwd": "{projectRoot}",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"echo2": {
|
"echo2": {
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "{projectRoot}",
|
"cwd": "{projectRoot}",
|
||||||
},
|
},
|
||||||
@ -483,6 +496,7 @@ describe('target-defaults plugin', () => {
|
|||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"command": "echo hi",
|
"command": "echo hi",
|
||||||
|
"metadata": {},
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
@ -504,6 +518,7 @@ describe('target-defaults plugin', () => {
|
|||||||
expect(result).toMatchInlineSnapshot(`
|
expect(result).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"command": "echo hi",
|
"command": "echo hi",
|
||||||
},
|
},
|
||||||
@ -524,6 +539,7 @@ describe('target-defaults plugin', () => {
|
|||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "build",
|
"script": "build",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -167,10 +167,15 @@ export function getTargetInfo(
|
|||||||
...packageJsonTarget?.options,
|
...packageJsonTarget?.options,
|
||||||
...projectJsonTarget?.options,
|
...projectJsonTarget?.options,
|
||||||
};
|
};
|
||||||
|
const metadata = {
|
||||||
|
...packageJsonTarget?.metadata,
|
||||||
|
...projectJsonTarget?.metadata,
|
||||||
|
};
|
||||||
|
|
||||||
if (projectJsonTarget?.command) {
|
if (projectJsonTarget?.command) {
|
||||||
return {
|
return {
|
||||||
command: projectJsonTarget?.command,
|
command: projectJsonTarget?.command,
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +186,7 @@ export function getTargetInfo(
|
|||||||
options: {
|
options: {
|
||||||
command: targetOptions?.command,
|
command: targetOptions?.command,
|
||||||
},
|
},
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
} else if (targetOptions?.commands) {
|
} else if (targetOptions?.commands) {
|
||||||
return {
|
return {
|
||||||
@ -188,10 +194,12 @@ export function getTargetInfo(
|
|||||||
options: {
|
options: {
|
||||||
commands: targetOptions.commands,
|
commands: targetOptions.commands,
|
||||||
},
|
},
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
executor: 'nx:run-commands',
|
executor: 'nx:run-commands',
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,6 +209,7 @@ export function getTargetInfo(
|
|||||||
options: {
|
options: {
|
||||||
script: targetOptions?.script ?? target,
|
script: targetOptions?.script ?? target,
|
||||||
},
|
},
|
||||||
|
metadata,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,23 +29,35 @@ describe('readTargetsFromPackageJson', () => {
|
|||||||
options: {
|
options: {
|
||||||
script: 'build',
|
script: 'build',
|
||||||
},
|
},
|
||||||
|
metadata: {
|
||||||
|
runCommand: 'npm run build',
|
||||||
|
scriptContent: 'echo 1',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
it('should read targets from project.json and package.json', () => {
|
it('should read targets from project.json and package.json', () => {
|
||||||
const result = readTargetsFromPackageJson(packageJson);
|
const result = readTargetsFromPackageJson(packageJson);
|
||||||
expect(result).toEqual({
|
expect(result).toMatchInlineSnapshot(`
|
||||||
build: {
|
{
|
||||||
executor: 'nx:run-script',
|
"build": {
|
||||||
options: {
|
"executor": "nx:run-script",
|
||||||
script: 'build',
|
"metadata": {
|
||||||
|
"runCommand": "npm run build",
|
||||||
|
"scriptContent": "echo 1",
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"script": "build",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
"nx-release-publish": {
|
||||||
'nx-release-publish': {
|
"dependsOn": [
|
||||||
dependsOn: ['^nx-release-publish'],
|
"^nx-release-publish",
|
||||||
executor: '@nx/js:release-publish',
|
],
|
||||||
options: {},
|
"executor": "@nx/js:release-publish",
|
||||||
},
|
"options": {},
|
||||||
});
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should contain extended options from nx property in package.json', () => {
|
it('should contain extended options from nx property in package.json', () => {
|
||||||
@ -86,17 +98,27 @@ describe('readTargetsFromPackageJson', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toMatchInlineSnapshot(`
|
||||||
test: {
|
{
|
||||||
executor: 'nx:run-script',
|
"nx-release-publish": {
|
||||||
options: { script: 'test' },
|
"dependsOn": [
|
||||||
},
|
"^nx-release-publish",
|
||||||
'nx-release-publish': {
|
],
|
||||||
dependsOn: ['^nx-release-publish'],
|
"executor": "@nx/js:release-publish",
|
||||||
executor: '@nx/js:release-publish',
|
"options": {},
|
||||||
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', () => {
|
it('should extend script based targets if matching config', () => {
|
||||||
@ -117,6 +139,10 @@ describe('readTargetsFromPackageJson', () => {
|
|||||||
expect(result.build).toMatchInlineSnapshot(`
|
expect(result.build).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
"executor": "nx:run-script",
|
"executor": "nx:run-script",
|
||||||
|
"metadata": {
|
||||||
|
"runCommand": "npm run build",
|
||||||
|
"scriptContent": "echo 1",
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"script": "build",
|
"script": "build",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
import { mergeTargetConfigurations } from '../project-graph/utils/project-configuration-utils';
|
import { mergeTargetConfigurations } from '../project-graph/utils/project-configuration-utils';
|
||||||
import { readJsonFile } from './fileutils';
|
import { readJsonFile } from './fileutils';
|
||||||
import { getNxRequirePaths } from './installation-directory';
|
import { getNxRequirePaths } from './installation-directory';
|
||||||
|
import { getPackageManagerCommand } from './package-manager';
|
||||||
|
|
||||||
export interface NxProjectPackageJsonConfiguration {
|
export interface NxProjectPackageJsonConfiguration {
|
||||||
implicitDependencies?: string[];
|
implicitDependencies?: string[];
|
||||||
@ -115,12 +116,20 @@ export function readNxMigrateConfig(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildTargetFromScript(script: string): TargetConfiguration {
|
export function buildTargetFromScript(
|
||||||
|
script: string,
|
||||||
|
scripts: Record<string, string> = {}
|
||||||
|
): TargetConfiguration {
|
||||||
|
const packageManagerCommand = getPackageManagerCommand();
|
||||||
return {
|
return {
|
||||||
executor: 'nx:run-script',
|
executor: 'nx:run-script',
|
||||||
options: {
|
options: {
|
||||||
script,
|
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 ?? {});
|
const includedScripts = nx?.includedScripts || Object.keys(scripts ?? {});
|
||||||
//
|
//
|
||||||
for (const script of includedScripts) {
|
for (const script of includedScripts) {
|
||||||
res[script] = buildTargetFromScript(script);
|
res[script] = buildTargetFromScript(script, scripts);
|
||||||
}
|
}
|
||||||
for (const targetName in nx?.targets) {
|
for (const targetName in nx?.targets) {
|
||||||
res[targetName] = mergeTargetConfigurations(
|
res[targetName] = mergeTargetConfigurations(
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export interface PackageManagerCommands {
|
|||||||
exec: string;
|
exec: string;
|
||||||
dlx: string;
|
dlx: string;
|
||||||
list: string;
|
list: string;
|
||||||
run: (script: string, args: string) => string;
|
run: (script: string, args?: string) => string;
|
||||||
getRegistryUrl: string;
|
getRegistryUrl: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,8 @@ export function getPackageManagerCommand(
|
|||||||
rm: 'yarn remove',
|
rm: 'yarn remove',
|
||||||
exec: 'yarn',
|
exec: 'yarn',
|
||||||
dlx: useBerry ? 'yarn dlx' : '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',
|
list: useBerry ? 'yarn info --name-only' : 'yarn list',
|
||||||
getRegistryUrl: useBerry
|
getRegistryUrl: useBerry
|
||||||
? 'yarn config get npmRegistryServer'
|
? 'yarn config get npmRegistryServer'
|
||||||
@ -122,10 +123,14 @@ export function getPackageManagerCommand(
|
|||||||
rm: 'pnpm rm',
|
rm: 'pnpm rm',
|
||||||
exec: modernPnpm ? 'pnpm exec' : 'pnpx',
|
exec: modernPnpm ? 'pnpm exec' : 'pnpx',
|
||||||
dlx: modernPnpm ? 'pnpm dlx' : 'pnpx',
|
dlx: modernPnpm ? 'pnpm dlx' : 'pnpx',
|
||||||
run: (script: string, args: string) =>
|
run: (script: string, args?: string) =>
|
||||||
includeDoubleDashBeforeArgs
|
`pnpm run ${script}${
|
||||||
? `pnpm run ${script} -- ${args}`
|
args
|
||||||
: `pnpm run ${script} ${args}`,
|
? includeDoubleDashBeforeArgs
|
||||||
|
? ' -- ' + args
|
||||||
|
: ` ${args}`
|
||||||
|
: ''
|
||||||
|
}`,
|
||||||
list: 'pnpm ls --depth 100',
|
list: 'pnpm ls --depth 100',
|
||||||
getRegistryUrl: 'pnpm config get registry',
|
getRegistryUrl: 'pnpm config get registry',
|
||||||
};
|
};
|
||||||
@ -143,7 +148,8 @@ export function getPackageManagerCommand(
|
|||||||
rm: 'npm rm',
|
rm: 'npm rm',
|
||||||
exec: 'npx',
|
exec: 'npx',
|
||||||
dlx: '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',
|
list: 'npm ls',
|
||||||
getRegistryUrl: 'npm config get registry',
|
getRegistryUrl: 'npm config get registry',
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user