Skip to content

core: dep-graph creates invalid dependencies #8938

@Hotell

Description

@Hotell

Current Behavior

if project A includes static import or require statement to another workspace project within a string (lets say project B), nx will incorrectly resolve this as a dependency on that project, which leads to incorrect project graph creation

  • thus running unnecessary packages on CI
  • and also giving miss leading output when running nx graph.

UPDATE:

🎬 I was able to narrow down the AST parsing issue and the culprit is template string! whenever there is one being used and followed by string that includes static import then we run into wrong dependency tree resolution.

// @filename packages/proj-a/index.js

const npmScope = 'myorg';
// 🚨 this is the root cause - interpolating template literals 
console.log(`@${npmScope}`);


// 🚨 now your project depends on proj-b ( which is not true )
console.log(`import {foo} from '@my-org/proj-b'`)

following will properly resolve the AST

// @filename packages/proj-a/index.js

const npmScope = 'myorg';
// ✅ no template strings, AST works
console.log('@' + npmScope);


// ✅ this will do no harm as expected
console.log(`import {foo} from '@my-org/proj-b'`)

Expected Behavior

dep-graph creation should ignore static import/require statements included as strings during AST parsing.

Steps to Reproduce

NOTE: download the project to try it out without hassle
ast-issue-dep-graph.tar.gz

  1. remove cache `rm -rf node_modules/.cache/nx
  2. create 2 projects that contain following:
// @filename packages/proj-b/index.js

export const foo = 'hello'
// @filename packages/proj-a/index.js

const npmScope = 'myorg';
// 🚨 this is the root cause - interpolating template literals 
console.log(`@${npmScope}`);

console.log(`import {foo} from '@my-org/proj-b'`);

export const moo = 'world'
  1. run following script:
// @filename repro.js
const { readCachedProjectGraph, createProjectGraphAsync } = require('@nrwl/workspace/src/core/project-graph');

main();

async function main() {
  const graph = await createProjectGraphAsync()

  console.log(
    JSON.stringify({
      nodes: graph.nodes['@my-org/proj-a'],
      deps: graph.dependencies['@my-org/proj-a'],
    }),
  );
}
  • this will result into following node definition:
{
          "file": "packages/proj-a/index.js",
          "hash": "15789608a71660844b9f5822cf3f2ed2c473ddf2",
          "deps": ["@fluentui/proj-b"]
},
  • this will result into following dependencies definition:
{ "source": "@my-org/proj-a", "target": "@my-org/proj-b", "type": "static" },

there should be no @my-org/proj-b as a dependency

Failure Logs

Environment

 Node : 14.18.1
   OS   : darwin x64
   yarn : 1.23.34
   
   nx : 13.8.1
   @nrwl/angular : undefined
   @nrwl/cli : 13.8.1
   @nrwl/cypress : undefined
   @nrwl/detox : undefined
   @nrwl/devkit : 13.8.1
   @nrwl/eslint-plugin-nx : undefined
   @nrwl/express : undefined
   @nrwl/jest : 13.8.1
   @nrwl/js : 13.8.1
   @nrwl/linter : 13.8.1
   @nrwl/nest : undefined
   @nrwl/next : undefined
   @nrwl/node : 13.8.1
   @nrwl/nx-cloud : undefined
   @nrwl/react : undefined
   @nrwl/react-native : undefined
   @nrwl/schematics : undefined
   @nrwl/storybook : undefined
   @nrwl/tao : 13.8.1
   @nrwl/web : undefined
   @nrwl/workspace : 13.8.1
   typescript : 4.3.5
   rxjs : 6.6.7

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions