feat(core): add --help content to project details view (#26629)
This PR adds help text for each inferred target that provides
`metadata.help.command`. To pass options/args to the target, users are
directed to open `project.json` and copy the values from `--help` output
into `options` property of the target.
To display the options help section, the inferred target must provide
metadata as follows:
```json5
metadata: {
help: {
command: `foo --help`
example: {
options: {
bar: true
},
},
},
},
```
The `help.command` value will be used to retrieve help text for the
underlying CLI (e.g. `jest --help`). The `help.example` property
contains sample options and args that users can add to their
`project.json` file -- currently rendered in the hover tooltip of
`project.json` hint text.
---
Example with `vite build --help`:
<img width="1257" alt="Screenshot 2024-06-21 at 3 06 21 PM"
src="https://github.com/nrwl/nx/assets/53559/b94cdcde-80da-4fa5-9f93-11af7fbcaf27">
Result of clicking `Run`:
<img width="1257" alt="Screenshot 2024-06-21 at 3 06 24 PM"
src="https://github.com/nrwl/nx/assets/53559/6803a5a8-9bbd-4510-b9ff-fa895a5b3402">
`project.json` tooltip hint:
<img width="1392" alt="Screenshot 2024-06-25 at 12 44 02 PM"
src="https://github.com/nrwl/nx/assets/53559/565002ae-7993-4dda-ac5d-4b685710f65e">
This commit is contained in:
parent
df83dd4c6e
commit
d90a735540
@ -10,7 +10,7 @@ export function useEnvironmentConfig(): {
|
||||
watch: boolean;
|
||||
localMode: 'serve' | 'build';
|
||||
projectGraphResponse?: ProjectGraphClientResponse;
|
||||
environment: 'dev' | 'watch' | 'release' | 'nx-console';
|
||||
environment: 'dev' | 'watch' | 'release' | 'nx-console' | 'docs';
|
||||
appConfig: AppConfig;
|
||||
useXstateInspect: boolean;
|
||||
} {
|
||||
@ -25,13 +25,14 @@ export function getEnvironmentConfig() {
|
||||
watch: window.watch,
|
||||
localMode: window.localMode,
|
||||
projectGraphResponse: window.projectGraphResponse,
|
||||
environment: window.environment,
|
||||
// If this was not built into JS or HTML, then it is rendered on docs (nx.dev).
|
||||
environment: window.environment ?? ('docs' as const),
|
||||
appConfig: {
|
||||
...window.appConfig,
|
||||
showExperimentalFeatures:
|
||||
localStorage.getItem('showExperimentalFeatures') === 'true'
|
||||
? true
|
||||
: window.appConfig.showExperimentalFeatures,
|
||||
: window.appConfig?.showExperimentalFeatures,
|
||||
},
|
||||
useXstateInspect: window.useXstateInspect,
|
||||
};
|
||||
|
||||
@ -0,0 +1,198 @@
|
||||
import { Fragment, ReactNode, useMemo, useState } from 'react';
|
||||
import { PlayIcon, XMarkIcon } from '@heroicons/react/24/outline';
|
||||
import { Transition } from '@headlessui/react';
|
||||
import { getExternalApiService, useEnvironmentConfig } from '@nx/graph/shared';
|
||||
/* eslint-disable @nx/enforce-module-boundaries */
|
||||
// nx-ignore-next-line
|
||||
import type { TargetConfiguration } from '@nx/devkit';
|
||||
import { TerminalOutput } from '@nx/nx-dev/ui-fence';
|
||||
import { Tooltip } from '@nx/graph/ui-tooltips';
|
||||
import { TooltipTriggerText } from '../target-configuration-details/tooltip-trigger-text';
|
||||
|
||||
interface ShowOptionsHelpProps {
|
||||
projectName: string;
|
||||
targetName: string;
|
||||
targetConfiguration: TargetConfiguration;
|
||||
}
|
||||
|
||||
const fallbackHelpExample = {
|
||||
options: {
|
||||
silent: true,
|
||||
},
|
||||
args: ['foo'],
|
||||
};
|
||||
|
||||
export function ShowOptionsHelp({
|
||||
projectName,
|
||||
targetName,
|
||||
targetConfiguration,
|
||||
}: ShowOptionsHelpProps) {
|
||||
const config = useEnvironmentConfig();
|
||||
const environment = config?.environment;
|
||||
const localMode = config?.localMode;
|
||||
const [result, setResult] = useState<{
|
||||
text: string;
|
||||
success: boolean;
|
||||
} | null>(null);
|
||||
const [isPending, setPending] = useState(false);
|
||||
const externalApiService = getExternalApiService();
|
||||
|
||||
const helpData = targetConfiguration.metadata?.help;
|
||||
const helpCommand = helpData?.command;
|
||||
const helpExampleOptions = helpData?.example?.options;
|
||||
const helpExampleArgs = helpData?.example?.args;
|
||||
|
||||
const helpExampleTest = useMemo(() => {
|
||||
const targetExampleJson =
|
||||
helpExampleOptions || helpExampleArgs
|
||||
? {
|
||||
options: helpExampleOptions,
|
||||
args: helpExampleArgs,
|
||||
}
|
||||
: fallbackHelpExample;
|
||||
return JSON.stringify(
|
||||
{
|
||||
targets: {
|
||||
[targetName]: targetExampleJson,
|
||||
},
|
||||
},
|
||||
null,
|
||||
2
|
||||
);
|
||||
}, [helpExampleOptions, helpExampleArgs]);
|
||||
|
||||
let runHelpActionElement: null | ReactNode;
|
||||
if (environment === 'docs') {
|
||||
// Cannot run help command when rendering in docs (e.g. nx.dev).
|
||||
runHelpActionElement = null;
|
||||
} else if (environment === 'release' && localMode === 'build') {
|
||||
// Cannot run help command when statically built via `nx graph --file=graph.html`.
|
||||
runHelpActionElement = null;
|
||||
} else if (isPending || !result) {
|
||||
runHelpActionElement = (
|
||||
<button
|
||||
className="flex items-center rounded-md border border-slate-500 px-1 disabled:opacity-75"
|
||||
disabled={isPending}
|
||||
onClick={
|
||||
environment === 'nx-console'
|
||||
? () => {
|
||||
externalApiService.postEvent({
|
||||
type: 'run-help',
|
||||
payload: {
|
||||
projectName,
|
||||
targetName,
|
||||
helpCommand,
|
||||
},
|
||||
});
|
||||
}
|
||||
: async () => {
|
||||
setPending(true);
|
||||
const result = await fetch(
|
||||
`/help?project=${encodeURIComponent(
|
||||
projectName
|
||||
)}&target=${encodeURIComponent(targetName)}`
|
||||
).then((resp) => resp.json());
|
||||
setResult(result);
|
||||
setPending(false);
|
||||
}
|
||||
}
|
||||
>
|
||||
<PlayIcon className="mr-1 h-4 w-4" />
|
||||
Run
|
||||
</button>
|
||||
);
|
||||
} else {
|
||||
runHelpActionElement = (
|
||||
<button
|
||||
className="flex items-center rounded-md border border-slate-500 px-1"
|
||||
onClick={() => setResult(null)}
|
||||
>
|
||||
<XMarkIcon className="mr-1 h-4 w-4" />
|
||||
Clear output
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
helpCommand && (
|
||||
<>
|
||||
<p className="mb-4">
|
||||
Use <code>--help</code> to see all options for this command, and set
|
||||
them by{' '}
|
||||
<a
|
||||
className="text-blue-500 hover:underline"
|
||||
target="_blank"
|
||||
href="https://nx.dev/recipes/running-tasks/pass-args-to-commands#pass-args-to-commands"
|
||||
>
|
||||
passing them
|
||||
</a>{' '}
|
||||
to the <code>"options"</code> property in{' '}
|
||||
<Tooltip
|
||||
openAction="hover"
|
||||
content={
|
||||
(
|
||||
<div className="w-fit max-w-md">
|
||||
<p className="mb-2">
|
||||
For example, you can use the following configuration for the{' '}
|
||||
<code>{targetName}</code> target in the{' '}
|
||||
<code>project.json</code> file for{' '}
|
||||
<span className="font-semibold">{projectName}</span>.
|
||||
</p>
|
||||
<pre className="mb-2 border border-slate-200 bg-slate-100/50 p-2 p-2 text-slate-400 dark:border-slate-700 dark:bg-slate-700/50 dark:text-slate-500">
|
||||
{helpExampleTest}
|
||||
</pre>
|
||||
{helpExampleOptions && (
|
||||
<p className="mb-2">
|
||||
The <code>options</code> are CLI options prefixed by{' '}
|
||||
<code>--</code>, such as <code>ls --color=never</code>,
|
||||
where you would use <code>{'"color": "never"'}</code> to
|
||||
set it in the target configuration.
|
||||
</p>
|
||||
)}
|
||||
{helpExampleArgs && (
|
||||
<p className="mb-2">
|
||||
The <code>args</code> are CLI positional arguments, such
|
||||
as <code>ls somedir</code>, where you would use{' '}
|
||||
<code>{'"args": ["somedir"]'}</code> to set it in the
|
||||
target configuration.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
) as any
|
||||
}
|
||||
>
|
||||
<code>
|
||||
<TooltipTriggerText>project.json</TooltipTriggerText>
|
||||
</code>
|
||||
</Tooltip>
|
||||
.
|
||||
</p>
|
||||
<TerminalOutput
|
||||
command={helpCommand}
|
||||
path={targetConfiguration.options.cwd ?? ''}
|
||||
actionElement={runHelpActionElement}
|
||||
content={
|
||||
<div className="relative w-full">
|
||||
<Transition
|
||||
show={!!result}
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0 translate-y-1"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in duration-100"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<pre
|
||||
className={result && !result.success ? 'text-red-500' : ''}
|
||||
>
|
||||
{result?.text}
|
||||
</pre>
|
||||
</Transition>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -17,6 +17,7 @@ import { TargetExecutor } from '../target-executor/target-executor';
|
||||
import { TargetExecutorTitle } from '../target-executor/target-executor-title';
|
||||
import { TargetSourceInfo } from '../target-source-info/target-source-info';
|
||||
import { getTargetExecutorSourceMapKey } from '../target-source-info/get-target-executor-source-map-key';
|
||||
import { ShowOptionsHelp } from '../show-all-options/show-options-help';
|
||||
|
||||
interface TargetConfigurationDetailsProps {
|
||||
projectName: string;
|
||||
@ -85,7 +86,7 @@ export default function TargetConfigurationDetails({
|
||||
: true);
|
||||
|
||||
return (
|
||||
<div className="relative overflow-hidden rounded-md border border-slate-200 dark:border-slate-700/60">
|
||||
<div className="relative rounded-md border border-slate-200 dark:border-slate-700/60">
|
||||
<TargetConfigurationDetailsHeader
|
||||
isCollasped={collapsed}
|
||||
toggleCollapse={handleCollapseToggle}
|
||||
@ -141,6 +142,44 @@ export default function TargetConfigurationDetails({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldRenderOptions ? (
|
||||
<>
|
||||
<h4 className="mb-4">
|
||||
<Tooltip
|
||||
openAction="hover"
|
||||
content={(<PropertyInfoTooltip type="options" />) as any}
|
||||
>
|
||||
<span className="font-medium">
|
||||
<TooltipTriggerText>Options</TooltipTriggerText>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</h4>
|
||||
<div className="mb-4">
|
||||
<FadingCollapsible>
|
||||
<JsonCodeBlock
|
||||
data={options}
|
||||
renderSource={(propertyName: string) => (
|
||||
<TargetSourceInfo
|
||||
className="flex min-w-0 pl-4"
|
||||
propertyKey={`targets.${targetName}.options.${propertyName}`}
|
||||
sourceMap={sourceMap}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FadingCollapsible>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<ShowOptionsHelp
|
||||
targetConfiguration={targetConfiguration}
|
||||
projectName={projectName}
|
||||
targetName={targetName}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{targetConfiguration.inputs && (
|
||||
<div className="group">
|
||||
<h4 className="mb-4">
|
||||
@ -265,37 +304,6 @@ export default function TargetConfigurationDetails({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{shouldRenderOptions ? (
|
||||
<>
|
||||
<h4 className="mb-4">
|
||||
<Tooltip
|
||||
openAction="hover"
|
||||
content={(<PropertyInfoTooltip type="options" />) as any}
|
||||
>
|
||||
<span className="font-medium">
|
||||
<TooltipTriggerText>Options</TooltipTriggerText>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</h4>
|
||||
<div className="mb-4">
|
||||
<FadingCollapsible>
|
||||
<JsonCodeBlock
|
||||
data={options}
|
||||
renderSource={(propertyName: string) => (
|
||||
<TargetSourceInfo
|
||||
className="flex min-w-0 pl-4"
|
||||
propertyKey={`targets.${targetName}.options.${propertyName}`}
|
||||
sourceMap={sourceMap}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FadingCollapsible>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{shouldRenderConfigurations ? (
|
||||
<>
|
||||
<h4 className="mb-4 py-2">
|
||||
|
||||
@ -1,20 +1,22 @@
|
||||
import { ReactNode } from 'react';
|
||||
import type { JSX, ReactNode } from 'react';
|
||||
import { TerminalShellWrapper } from './terminal-shell';
|
||||
|
||||
export function TerminalOutput({
|
||||
content,
|
||||
command,
|
||||
path,
|
||||
actionElement,
|
||||
}: {
|
||||
content: ReactNode | null;
|
||||
content: ReactNode;
|
||||
command: string;
|
||||
path: string;
|
||||
actionElement?: ReactNode;
|
||||
}): JSX.Element {
|
||||
const commandLines = command.split('\n').filter(Boolean);
|
||||
return (
|
||||
<TerminalShellWrapper>
|
||||
<div className="overflow-x-auto p-4 pt-2">
|
||||
<div className="items-left flex flex-col">
|
||||
<div className="items-left relative flex flex-col">
|
||||
{commandLines.map((line, index) => {
|
||||
return (
|
||||
<div key={index} className="flex">
|
||||
@ -29,6 +31,9 @@ export function TerminalOutput({
|
||||
</span>
|
||||
</p>
|
||||
<p className="typing mt-0.5 flex-1 pl-2">{line}</p>
|
||||
{actionElement ? (
|
||||
<div className="sticky top-0 pl-2">{actionElement}</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@ -101,6 +101,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests",
|
||||
"help": {
|
||||
"command": "npx cypress run --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--headed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
@ -117,6 +126,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"help": {
|
||||
"command": "npx cypress open --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--e2e",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
@ -179,6 +197,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Component Tests",
|
||||
"help": {
|
||||
"command": "npx cypress run --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--headed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
@ -195,6 +222,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"help": {
|
||||
"command": "npx cypress open --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--e2e",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
@ -273,6 +309,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests",
|
||||
"help": {
|
||||
"command": "npx cypress run --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--headed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
@ -306,6 +351,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests in CI",
|
||||
"help": {
|
||||
"command": "npx cypress run --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--headed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
@ -330,6 +384,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests in src/test.cy.ts in CI",
|
||||
"help": {
|
||||
"command": "npx cypress run --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--headed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
@ -347,6 +410,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"help": {
|
||||
"command": "npx cypress open --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--dev",
|
||||
"--e2e",
|
||||
],
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
|
||||
@ -4,6 +4,7 @@ import {
|
||||
createNodesFromFiles,
|
||||
CreateNodesV2,
|
||||
detectPackageManager,
|
||||
getPackageManagerCommand,
|
||||
joinPathFragments,
|
||||
logger,
|
||||
normalizePath,
|
||||
@ -44,6 +45,8 @@ function writeTargetsToCache(cachePath: string, results: CypressTargets) {
|
||||
|
||||
const cypressConfigGlob = '**/cypress.config.{js,ts,mjs,cjs}';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export const createNodesV2: CreateNodesV2<CypressPluginOptions> = [
|
||||
cypressConfigGlob,
|
||||
async (configFiles, options, context) => {
|
||||
@ -211,6 +214,12 @@ async function buildCypressTargets(
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Tests',
|
||||
help: {
|
||||
command: `${pmc.exec} cypress run --help`,
|
||||
example: {
|
||||
args: ['--dev', '--headed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -271,6 +280,12 @@ async function buildCypressTargets(
|
||||
technologies: ['cypress'],
|
||||
description: `Runs Cypress Tests in ${relativeSpecFilePath} in CI`,
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} cypress run --help`,
|
||||
example: {
|
||||
args: ['--dev', '--headed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
dependsOn.push({
|
||||
@ -290,6 +305,12 @@ async function buildCypressTargets(
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Tests in CI',
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} cypress run --help`,
|
||||
example: {
|
||||
args: ['--dev', '--headed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
ciTargetGroup.push(options.ciTargetName);
|
||||
@ -307,6 +328,12 @@ async function buildCypressTargets(
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Component Tests',
|
||||
help: {
|
||||
command: `${pmc.exec} cypress run --help`,
|
||||
example: {
|
||||
args: ['--dev', '--headed'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@ -317,6 +344,12 @@ async function buildCypressTargets(
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Opens Cypress',
|
||||
help: {
|
||||
command: `${pmc.exec} cypress open --help`,
|
||||
example: {
|
||||
args: ['--dev', '--e2e'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -114,6 +114,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -155,6 +169,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -227,6 +255,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/my-app",
|
||||
},
|
||||
@ -268,6 +310,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/my-app",
|
||||
},
|
||||
@ -381,6 +437,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/my-app",
|
||||
},
|
||||
@ -406,6 +476,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
@ -491,6 +575,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/my-app",
|
||||
},
|
||||
@ -517,6 +615,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "libs/my-lib",
|
||||
},
|
||||
@ -560,6 +672,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/myapp",
|
||||
},
|
||||
@ -608,6 +734,20 @@ describe('@nx/eslint/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs ESLint on project",
|
||||
"help": {
|
||||
"command": "npx eslint --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"max-warnings": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"eslint",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "apps/myapp/nested/mylib",
|
||||
},
|
||||
|
||||
@ -2,12 +2,13 @@ import {
|
||||
CreateNodes,
|
||||
CreateNodesContext,
|
||||
CreateNodesContextV2,
|
||||
createNodesFromFiles,
|
||||
CreateNodesResult,
|
||||
CreateNodesV2,
|
||||
TargetConfiguration,
|
||||
createNodesFromFiles,
|
||||
getPackageManagerCommand,
|
||||
logger,
|
||||
readJsonFile,
|
||||
TargetConfiguration,
|
||||
writeJsonFile,
|
||||
} from '@nx/devkit';
|
||||
import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash-for-create-nodes';
|
||||
@ -19,13 +20,15 @@ import { combineGlobPatterns } from 'nx/src/utils/globs';
|
||||
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||
import { gte } from 'semver';
|
||||
import {
|
||||
ESLINT_CONFIG_FILENAMES,
|
||||
baseEsLintConfigFile,
|
||||
baseEsLintFlatConfigFile,
|
||||
ESLINT_CONFIG_FILENAMES,
|
||||
isFlatConfig,
|
||||
} from '../utils/config-file';
|
||||
import { resolveESLintClass } from '../utils/resolve-eslint-class';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export interface EslintPluginOptions {
|
||||
targetName?: string;
|
||||
extensions?: string[];
|
||||
@ -453,7 +456,6 @@ function buildEslintTargets(
|
||||
standaloneSrcPath?: string
|
||||
) {
|
||||
const isRootProject = projectRoot === '.';
|
||||
|
||||
const targets: Record<string, TargetConfiguration> = {};
|
||||
|
||||
const targetConfig: TargetConfiguration = {
|
||||
@ -481,6 +483,18 @@ function buildEslintTargets(
|
||||
{ externalDependencies: ['eslint'] },
|
||||
],
|
||||
outputs: ['{options.outputFile}'],
|
||||
metadata: {
|
||||
technologies: ['eslint'],
|
||||
description: 'Runs ESLint on project',
|
||||
help: {
|
||||
command: `${pmc.exec} eslint --help`,
|
||||
example: {
|
||||
options: {
|
||||
'max-warnings': 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Always set the environment variable to ensure that the ESLint CLI can run on eslint v8 and v9
|
||||
|
||||
157
packages/jest/src/plugins/__snapshots__/plugin.spec.ts.snap
Normal file
157
packages/jest/src/plugins/__snapshots__/plugin.spec.ts.snap
Normal file
@ -0,0 +1,157 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`@nx/jest/plugin should add package as externalDependencies to the inputs when specified as preset and containing a jest-preset.cjs file 1`] = `
|
||||
[
|
||||
[
|
||||
"proj/jest.config.js",
|
||||
{
|
||||
"projects": {
|
||||
"proj": {
|
||||
"metadata": undefined,
|
||||
"root": "proj",
|
||||
"targets": {
|
||||
"test": {
|
||||
"cache": true,
|
||||
"command": "jest",
|
||||
"inputs": [
|
||||
"default",
|
||||
"^production",
|
||||
{
|
||||
"externalDependencies": [
|
||||
"jest",
|
||||
"some-package",
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
},
|
||||
"outputs": [
|
||||
"{workspaceRoot}/coverage",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`@nx/jest/plugin should add package as externalDependencies to the inputs when specified as preset and containing a jest-preset.js file 1`] = `
|
||||
[
|
||||
[
|
||||
"proj/jest.config.js",
|
||||
{
|
||||
"projects": {
|
||||
"proj": {
|
||||
"metadata": undefined,
|
||||
"root": "proj",
|
||||
"targets": {
|
||||
"test": {
|
||||
"cache": true,
|
||||
"command": "jest",
|
||||
"inputs": [
|
||||
"default",
|
||||
"^production",
|
||||
{
|
||||
"externalDependencies": [
|
||||
"jest",
|
||||
"some-package",
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
},
|
||||
"outputs": [
|
||||
"{workspaceRoot}/coverage",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`@nx/jest/plugin should add package as externalDependencies to the inputs when specified as preset and containing a jest-preset.json file 1`] = `
|
||||
[
|
||||
[
|
||||
"proj/jest.config.js",
|
||||
{
|
||||
"projects": {
|
||||
"proj": {
|
||||
"metadata": undefined,
|
||||
"root": "proj",
|
||||
"targets": {
|
||||
"test": {
|
||||
"cache": true,
|
||||
"command": "jest",
|
||||
"inputs": [
|
||||
"default",
|
||||
"^production",
|
||||
{
|
||||
"externalDependencies": [
|
||||
"jest",
|
||||
"some-package",
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
},
|
||||
"outputs": [
|
||||
"{workspaceRoot}/coverage",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
@ -82,6 +82,14 @@ describe('@nx/jest/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
@ -151,6 +159,14 @@ describe('@nx/jest/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
@ -179,6 +195,14 @@ describe('@nx/jest/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests in CI",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "test",
|
||||
"technologies": [
|
||||
"jest",
|
||||
@ -202,6 +226,14 @@ describe('@nx/jest/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests in src/unit.spec.ts",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "test",
|
||||
"technologies": [
|
||||
"jest",
|
||||
@ -261,6 +293,14 @@ describe('@nx/jest/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"help": {
|
||||
"command": "npx jest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
@ -305,49 +345,7 @@ describe('@nx/jest/plugin', () => {
|
||||
context
|
||||
);
|
||||
|
||||
expect(results).toMatchInlineSnapshot(`
|
||||
[
|
||||
[
|
||||
"proj/jest.config.js",
|
||||
{
|
||||
"projects": {
|
||||
"proj": {
|
||||
"metadata": undefined,
|
||||
"root": "proj",
|
||||
"targets": {
|
||||
"test": {
|
||||
"cache": true,
|
||||
"command": "jest",
|
||||
"inputs": [
|
||||
"default",
|
||||
"^production",
|
||||
{
|
||||
"externalDependencies": [
|
||||
"jest",
|
||||
"some-package",
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Jest Tests",
|
||||
"technologies": [
|
||||
"jest",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "proj",
|
||||
},
|
||||
"outputs": [
|
||||
"{workspaceRoot}/coverage",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
]
|
||||
`);
|
||||
expect(results).toMatchSnapshot();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
CreateNodesContext,
|
||||
createNodesFromFiles,
|
||||
CreateNodesV2,
|
||||
getPackageManagerCommand,
|
||||
joinPathFragments,
|
||||
logger,
|
||||
normalizePath,
|
||||
@ -29,6 +30,8 @@ import { combineGlobPatterns } from 'nx/src/utils/globs';
|
||||
import { minimatch } from 'minimatch';
|
||||
import { hashObject } from 'nx/src/devkit-internals';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export interface JestPluginOptions {
|
||||
targetName?: string;
|
||||
ciTargetName?: string;
|
||||
@ -55,6 +58,7 @@ export const createNodesV2: CreateNodesV2<JestPluginOptions> = [
|
||||
const optionsHash = hashObject(options);
|
||||
const cachePath = join(workspaceDataDirectory, `jest-${optionsHash}.hash`);
|
||||
const targetsCache = readTargetsCache(cachePath);
|
||||
|
||||
try {
|
||||
return await createNodesFromFiles(
|
||||
(configFile, options, context) =>
|
||||
@ -79,6 +83,7 @@ export const createNodes: CreateNodes<JestPluginOptions> = [
|
||||
logger.warn(
|
||||
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
|
||||
);
|
||||
|
||||
return createNodesInternal(...args, {});
|
||||
},
|
||||
];
|
||||
@ -184,6 +189,14 @@ async function buildJestTargets(
|
||||
metadata: {
|
||||
technologies: ['jest'],
|
||||
description: 'Run Jest Tests',
|
||||
help: {
|
||||
command: `${pmc.exec} jest --help`,
|
||||
example: {
|
||||
options: {
|
||||
coverage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -238,6 +251,14 @@ async function buildJestTargets(
|
||||
technologies: ['jest'],
|
||||
description: 'Run Jest Tests in CI',
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} jest --help`,
|
||||
example: {
|
||||
options: {
|
||||
coverage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
targetGroup.push(options.ciTargetName);
|
||||
@ -260,6 +281,14 @@ async function buildJestTargets(
|
||||
technologies: ['jest'],
|
||||
description: `Run Jest Tests in ${relativePath}`,
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} jest --help`,
|
||||
example: {
|
||||
options: {
|
||||
coverage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
targetGroup.push(targetName);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { createHash } from 'crypto';
|
||||
import { execSync } from 'node:child_process';
|
||||
import { existsSync, readFileSync, statSync, writeFileSync } from 'fs';
|
||||
import { copySync, ensureDirSync } from 'fs-extra';
|
||||
import * as http from 'http';
|
||||
@ -17,6 +18,7 @@ import {
|
||||
import { performance } from 'perf_hooks';
|
||||
import { readNxJson, workspaceLayout } from '../../config/configuration';
|
||||
import {
|
||||
FileData,
|
||||
ProjectFileMap,
|
||||
ProjectGraph,
|
||||
ProjectGraphDependency,
|
||||
@ -27,8 +29,6 @@ import { output } from '../../utils/output';
|
||||
import { workspaceRoot } from '../../utils/workspace-root';
|
||||
|
||||
import { Server } from 'net';
|
||||
|
||||
import { FileData } from '../../config/project-graph';
|
||||
import { TaskGraph } from '../../config/task-graph';
|
||||
import { daemonClient } from '../../daemon/client/client';
|
||||
import { getRootTsConfigPath } from '../../plugins/js/utils/typescript';
|
||||
@ -49,12 +49,10 @@ import { HashPlanner, transferProjectGraph } from '../../native';
|
||||
import { transformProjectGraphForRust } from '../../native/transform-objects';
|
||||
import { getAffectedGraphNodes } from '../affected/affected';
|
||||
import { readFileMapCache } from '../../project-graph/nx-deps-cache';
|
||||
import { Hash, getNamedInputs } from '../../hasher/task-hasher';
|
||||
import { filterUsingGlobPatterns } from '../../hasher/task-hasher';
|
||||
import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration-utils';
|
||||
|
||||
import { createTaskHasher } from '../../hasher/create-task-hasher';
|
||||
|
||||
import { filterUsingGlobPatterns } from '../../hasher/task-hasher';
|
||||
import { ProjectGraphError } from '../../project-graph/error-types';
|
||||
import { isNxCloudUsed } from '../../utils/nx-cloud-utils';
|
||||
|
||||
@ -600,6 +598,7 @@ async function startServer(
|
||||
'task input generation:start',
|
||||
'task input generation:end'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -621,6 +620,21 @@ async function startServer(
|
||||
return;
|
||||
}
|
||||
|
||||
if (sanitizePath === 'help') {
|
||||
const project = parsedUrl.searchParams.get('project');
|
||||
const target = parsedUrl.searchParams.get('target');
|
||||
|
||||
try {
|
||||
const text = getHelpTextFromTarget(project, target);
|
||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
||||
res.end(JSON.stringify({ text, success: true }));
|
||||
} catch (err) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
||||
res.end(JSON.stringify({ text: err.message, success: false }));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let pathname = join(__dirname, '../../core/graph/', sanitizePath);
|
||||
// if the file is not found or is a directory, return index.html
|
||||
if (!existsSync(pathname) || statSync(pathname).isDirectory()) {
|
||||
@ -1177,3 +1191,27 @@ async function createJsonOutput(
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
function getHelpTextFromTarget(
|
||||
projectName: string,
|
||||
targetName: string
|
||||
): string {
|
||||
if (!projectName) throw new Error(`Missing project`);
|
||||
if (!targetName) throw new Error(`Missing target`);
|
||||
|
||||
const project = currentProjectGraphClientResponse.projects?.find(
|
||||
(p) => p.name === projectName
|
||||
);
|
||||
if (!project) throw new Error(`Cannot find project ${projectName}`);
|
||||
|
||||
const target = project.data.targets[targetName];
|
||||
if (!target) throw new Error(`Cannot find target ${targetName}`);
|
||||
|
||||
const command = target.metadata?.help?.command;
|
||||
if (!command)
|
||||
throw new Error(`No help command found for ${projectName}:${targetName}`);
|
||||
|
||||
return execSync(command, {
|
||||
cwd: join(workspaceRoot, project.data.root),
|
||||
}).toString();
|
||||
}
|
||||
|
||||
@ -126,9 +126,17 @@ export interface ProjectMetadata {
|
||||
|
||||
export interface TargetMetadata {
|
||||
[k: string]: any;
|
||||
|
||||
description?: string;
|
||||
technologies?: string[];
|
||||
nonAtomizedTarget?: string;
|
||||
help?: {
|
||||
command: string;
|
||||
example: {
|
||||
options?: Record<string, unknown>;
|
||||
args?: string[];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export interface TargetDependencyConfig {
|
||||
|
||||
@ -73,6 +73,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"playwright",
|
||||
],
|
||||
@ -99,6 +107,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests in CI",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"playwright",
|
||||
@ -163,6 +179,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"playwright",
|
||||
],
|
||||
@ -192,6 +216,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests in CI",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"playwright",
|
||||
@ -275,6 +307,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests in CI",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"playwright",
|
||||
@ -300,6 +340,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests in tests/run-me.spec.ts in CI",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"playwright",
|
||||
@ -328,6 +376,14 @@ describe('@nx/playwright/plugin', () => {
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Playwright Tests in tests/run-me-2.spec.ts in CI",
|
||||
"help": {
|
||||
"command": "npx playwright test --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"workers": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
"nonAtomizedTarget": "e2e",
|
||||
"technologies": [
|
||||
"playwright",
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
createNodesFromFiles,
|
||||
CreateNodesV2,
|
||||
detectPackageManager,
|
||||
getPackageManagerCommand,
|
||||
joinPathFragments,
|
||||
logger,
|
||||
normalizePath,
|
||||
@ -26,6 +27,8 @@ import { getLockFileName } from '@nx/js';
|
||||
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';
|
||||
import { hashObject } from 'nx/src/hasher/file-hasher';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export interface PlaywrightPluginOptions {
|
||||
targetName?: string;
|
||||
ciTargetName?: string;
|
||||
@ -162,6 +165,14 @@ async function buildPlaywrightTargets(
|
||||
metadata: {
|
||||
technologies: ['playwright'],
|
||||
description: 'Runs Playwright Tests',
|
||||
help: {
|
||||
command: `${pmc.exec} playwright test --help`,
|
||||
example: {
|
||||
options: {
|
||||
workers: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -216,6 +227,14 @@ async function buildPlaywrightTargets(
|
||||
technologies: ['playwright'],
|
||||
description: `Runs Playwright Tests in ${relativeSpecFilePath} in CI`,
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} playwright test --help`,
|
||||
example: {
|
||||
options: {
|
||||
workers: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
dependsOn.push({
|
||||
@ -243,6 +262,14 @@ async function buildPlaywrightTargets(
|
||||
technologies: ['playwright'],
|
||||
description: 'Runs Playwright Tests in CI',
|
||||
nonAtomizedTarget: options.targetName,
|
||||
help: {
|
||||
command: `${pmc.exec} playwright test --help`,
|
||||
example: {
|
||||
options: {
|
||||
workers: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
ciTargetGroup.push(options.ciTargetName);
|
||||
|
||||
@ -25,6 +25,21 @@ exports[`@nx/vite/plugin root project should create nodes 1`] = `
|
||||
"env": "CI",
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Vite tests",
|
||||
"help": {
|
||||
"command": "npx vitest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"bail": 1,
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
|
||||
@ -25,6 +25,21 @@ exports[`@nx/vite/plugin with test node root project should create nodes - with
|
||||
"env": "CI",
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Vite tests",
|
||||
"help": {
|
||||
"command": "npx vitest --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"bail": 1,
|
||||
"coverage": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
|
||||
@ -26,6 +26,21 @@ exports[`@nx/vite/plugin Library mode should exclude serve and preview targets w
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Vite build",
|
||||
"help": {
|
||||
"command": "npx vite build --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"manifest": "manifest.json",
|
||||
"sourcemap": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "my-lib",
|
||||
},
|
||||
@ -67,6 +82,21 @@ exports[`@nx/vite/plugin not root project should create nodes 1`] = `
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Vite build",
|
||||
"help": {
|
||||
"command": "npx vite build --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"manifest": "manifest.json",
|
||||
"sourcemap": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "my-app",
|
||||
},
|
||||
@ -76,12 +106,40 @@ exports[`@nx/vite/plugin not root project should create nodes 1`] = `
|
||||
},
|
||||
"my-serve": {
|
||||
"command": "vite serve",
|
||||
"metadata": {
|
||||
"description": "Starts Vite dev server",
|
||||
"help": {
|
||||
"command": "npx vite --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"port": 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "my-app",
|
||||
},
|
||||
},
|
||||
"preview-site": {
|
||||
"command": "vite preview",
|
||||
"metadata": {
|
||||
"description": "Locally preview Vite production build",
|
||||
"help": {
|
||||
"command": "npx vite preview --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"port": 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": "my-app",
|
||||
},
|
||||
@ -127,6 +185,21 @@ exports[`@nx/vite/plugin root project should create nodes 1`] = `
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Run Vite build",
|
||||
"help": {
|
||||
"command": "npx vite build --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"manifest": "manifest.json",
|
||||
"sourcemap": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -136,12 +209,40 @@ exports[`@nx/vite/plugin root project should create nodes 1`] = `
|
||||
},
|
||||
"preview": {
|
||||
"command": "vite preview",
|
||||
"metadata": {
|
||||
"description": "Locally preview Vite production build",
|
||||
"help": {
|
||||
"command": "npx vite preview --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"port": 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
},
|
||||
"serve": {
|
||||
"command": "vite serve",
|
||||
"metadata": {
|
||||
"description": "Starts Vite dev server",
|
||||
"help": {
|
||||
"command": "npx vite --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"port": 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"vite",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
createNodesFromFiles,
|
||||
CreateNodesV2,
|
||||
detectPackageManager,
|
||||
getPackageManagerCommand,
|
||||
joinPathFragments,
|
||||
logger,
|
||||
ProjectConfiguration,
|
||||
@ -21,6 +22,8 @@ import { getLockFileName } from '@nx/js';
|
||||
import { loadViteDynamicImport } from '../utils/executor-utils';
|
||||
import { hashObject } from 'nx/src/hasher/file-hasher';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export interface VitePluginOptions {
|
||||
buildTargetName?: string;
|
||||
testTargetName?: string;
|
||||
@ -28,6 +31,7 @@ export interface VitePluginOptions {
|
||||
previewTargetName?: string;
|
||||
serveStaticTargetName?: string;
|
||||
}
|
||||
|
||||
type ViteTargets = Pick<ProjectConfiguration, 'targets' | 'metadata'>;
|
||||
|
||||
function readTargetsCache(cachePath: string): Record<string, ViteTargets> {
|
||||
@ -229,6 +233,19 @@ async function buildTarget(
|
||||
},
|
||||
],
|
||||
outputs,
|
||||
metadata: {
|
||||
technologies: ['vite'],
|
||||
description: `Run Vite build`,
|
||||
help: {
|
||||
command: `${pmc.exec} vite build --help`,
|
||||
example: {
|
||||
options: {
|
||||
sourcemap: true,
|
||||
manifest: 'manifest.json',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -238,6 +255,18 @@ function serveTarget(projectRoot: string) {
|
||||
options: {
|
||||
cwd: joinPathFragments(projectRoot),
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['vite'],
|
||||
description: `Starts Vite dev server`,
|
||||
help: {
|
||||
command: `${pmc.exec} vite --help`,
|
||||
example: {
|
||||
options: {
|
||||
port: 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return targetConfig;
|
||||
@ -249,6 +278,18 @@ function previewTarget(projectRoot: string) {
|
||||
options: {
|
||||
cwd: joinPathFragments(projectRoot),
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['vite'],
|
||||
description: `Locally preview Vite production build`,
|
||||
help: {
|
||||
command: `${pmc.exec} vite preview --help`,
|
||||
example: {
|
||||
options: {
|
||||
port: 3000,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return targetConfig;
|
||||
@ -275,6 +316,19 @@ async function testTarget(
|
||||
{ env: 'CI' },
|
||||
],
|
||||
outputs,
|
||||
metadata: {
|
||||
technologies: ['vite'],
|
||||
description: `Run Vite tests`,
|
||||
help: {
|
||||
command: `${pmc.exec} vitest --help`,
|
||||
example: {
|
||||
options: {
|
||||
bail: 1,
|
||||
coverage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,23 @@ exports[`@nx/webpack/plugin should create nodes 1`] = `
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Webpack build",
|
||||
"help": {
|
||||
"command": "npx webpack-cli build --help",
|
||||
"example": {
|
||||
"args": [
|
||||
"--profile",
|
||||
],
|
||||
"options": {
|
||||
"json": "stats.json",
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"webpack",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"args": [
|
||||
"--node-env=production",
|
||||
@ -37,6 +54,23 @@ exports[`@nx/webpack/plugin should create nodes 1`] = `
|
||||
},
|
||||
"my-serve": {
|
||||
"command": "webpack-cli serve",
|
||||
"metadata": {
|
||||
"description": "Starts Webpack dev server",
|
||||
"help": {
|
||||
"command": "npx webpack-cli serve --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"args": [
|
||||
"--client-progress",
|
||||
"--history-api-fallback ",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"webpack",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"args": [
|
||||
"--node-env=development",
|
||||
@ -46,6 +80,23 @@ exports[`@nx/webpack/plugin should create nodes 1`] = `
|
||||
},
|
||||
"preview-site": {
|
||||
"command": "webpack-cli serve",
|
||||
"metadata": {
|
||||
"description": "Starts Webpack dev server in production mode",
|
||||
"help": {
|
||||
"command": "npx webpack-cli serve --help",
|
||||
"example": {
|
||||
"options": {
|
||||
"args": [
|
||||
"--client-progress",
|
||||
"--history-api-fallback ",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"technologies": [
|
||||
"webpack",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"args": [
|
||||
"--node-env=production",
|
||||
|
||||
@ -6,6 +6,7 @@ import {
|
||||
CreateNodesResult,
|
||||
CreateNodesV2,
|
||||
detectPackageManager,
|
||||
getPackageManagerCommand,
|
||||
logger,
|
||||
ProjectConfiguration,
|
||||
readJsonFile,
|
||||
@ -23,6 +24,8 @@ import { dirname, isAbsolute, join, relative, resolve } from 'path';
|
||||
import { readWebpackOptions } from '../utils/webpack/read-webpack-options';
|
||||
import { resolveUserDefinedWebpackConfig } from '../utils/webpack/resolve-user-defined-webpack-config';
|
||||
|
||||
const pmc = getPackageManagerCommand();
|
||||
|
||||
export interface WebpackPluginOptions {
|
||||
buildTargetName?: string;
|
||||
serveTargetName?: string;
|
||||
@ -176,6 +179,19 @@ async function createWebpackTargets(
|
||||
},
|
||||
],
|
||||
outputs: [outputPath],
|
||||
metadata: {
|
||||
technologies: ['webpack'],
|
||||
description: 'Runs Webpack build',
|
||||
help: {
|
||||
command: `${pmc.exec} webpack-cli build --help`,
|
||||
example: {
|
||||
options: {
|
||||
json: 'stats.json',
|
||||
},
|
||||
args: ['--profile'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
targets[options.serveTargetName] = {
|
||||
@ -184,6 +200,18 @@ async function createWebpackTargets(
|
||||
cwd: projectRoot,
|
||||
args: ['--node-env=development'],
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['webpack'],
|
||||
description: 'Starts Webpack dev server',
|
||||
help: {
|
||||
command: `${pmc.exec} webpack-cli serve --help`,
|
||||
example: {
|
||||
options: {
|
||||
args: ['--client-progress', '--history-api-fallback '],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
targets[options.previewTargetName] = {
|
||||
@ -192,6 +220,18 @@ async function createWebpackTargets(
|
||||
cwd: projectRoot,
|
||||
args: ['--node-env=production'],
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['webpack'],
|
||||
description: 'Starts Webpack dev server in production mode',
|
||||
help: {
|
||||
command: `${pmc.exec} webpack-cli serve --help`,
|
||||
example: {
|
||||
options: {
|
||||
args: ['--client-progress', '--history-api-fallback '],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
targets[options.serveStaticTargetName] = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user