madge icon indicating copy to clipboard operation
madge copied to clipboard

v6.0.0: Circular Dependencies with only one node?

Open carboneater opened this issue 2 years ago • 11 comments

I run madge in my pipelines as a spaghetti mitigation strategy.

Using madge 5, everything went swimmingly

$ npx -p madge@5 madge -c --ts-config tsconfig.json --extensions ts --warning .
Processed 23 files (515ms) 

✔ No circular dependency found!

Madge 6, and there comes warnings and a failure

$ npx -p madge@6 madge -c --ts-config tsconfig.json --extensions ts --warning .
Processed 23 files (575ms) (2 warnings)

✖ Found 1 circular dependency!

1) lib/focus.ts

✖ Skipped 2 files

./lib
../lib

I tried generating a graph to see where Madge 6 saw something new. Madge 5 prints a graph where all is good.

Madge 6 prints Processed 23 files (575ms) (2 warnings) then exits...

Can't tell what went wrong yet, but it feels like v6 broke something related to

import { stuff } from './lib'

carboneater avatar Jan 30 '23 14:01 carboneater

So I ran madge@6 in a debugger...

my lib/focus.ts file starts with

import type { HardwareType, IAttachmentManifest, ProductType } from "focus";
import type { AnyPayload, ILegacyPayload } from "../interface";
import { isLegacyPayload } from "./legacy_guard";

focus is an internal package we defined in our own @types/focus

the result.tree of createOutputFromOptions contains the following

[
  "interface.d.ts",
  "lib/focus.ts",
  "lib/legacy_guard.ts",
]

So, import {x} from 'focus' got mangled up as lib/focus.ts in there...

The whole tree seems to mistake a file for the package...
(snipped for relevant files)

{
  "lib/ab.ts": [
    "interface.d.ts",
    "lib/focus.ts",
    "lib/hackson_guards.ts",
    "lib/util.ts",
  ],
  "lib/awc.ts": [
    "lib/focus.ts",
  ],
  "lib/focus.ts": [
    "interface.d.ts",
    "lib/focus.ts",
    "lib/legacy_guard.ts",
  ],
  "lib/index.ts": [
    "lib/ab.ts",
    "lib/awc.ts",
    "lib/focus.ts",
    "lib/hackson_guards.ts",
    "lib/legacy_guard.ts",
    "lib/ob.ts",
    "lib/temperature.ts",
    "lib/ub.ts",
    "lib/util.ts",
  ],
  "lib/ob.ts": [
    "interface.d.ts",
    "lib/focus.ts",
    "lib/hackson_guards.ts",
    "lib/util.ts",
  ],
  "lib/temperature.ts": [
    "interface.d.ts",
    "lib/focus.ts",
    "lib/hackson_guards.ts",
  ],
  "lib/ub.ts": [
    "interface.d.ts",
    "lib/focus.ts",
    "lib/hackson_guards.ts",
    "lib/util.ts",
  ],
  "lib/util.ts": [
    "lib/focus.ts",
  ],
}

The only file that should really refer to lib/focus.ts is lib/index.ts. All the others import from the focus package

carboneater avatar Jan 30 '23 15:01 carboneater

@carboneater Thanks for reporting!

Although a detailed investigation has not yet been done, it appears that the behavior of the dependent libraries has changed, as the algorithm for generating the source code dependency tree has not changed.

https://github.com/pahen/madge/compare/v5.0.2...v6.0.0

Whether to raise this as an issue to the dependent libraries or to take it special care of it in this library needs to be discussed.

kamiazya avatar Jan 31 '23 06:01 kamiazya

I'm also experiencing false positives for circular dependencies in version 6 which were fine in version 5. Two of our files that do not import each other are reported as a circular dependency.


Update: it's failing for us because of our path aliases in tsconfig.json as @mx-bernhard mentions below.

vamcs avatar Jan 31 '23 15:01 vamcs

This seems to be the same problem that also causes #271 and the workaround that I've written there should also make the wrong resolutions disappear.

mx-bernhard avatar Feb 12 '23 09:02 mx-bernhard

FYI, the critical values that should be present in "tsConfig" entry is "moduleResolution": "node":

  "madge": {
    "baseDir": "./server",
    "fileExtensions": ["ts"],
    "tsConfig": {
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "lib": ["esnext", "dom"],
        "moduleResolution": "node"
      },

crystalfp avatar Mar 20 '23 10:03 crystalfp

yeah we are also experiencing these false positives in a case where we have a local file (utils/analytics.ts) with the same name as a npm package (analytics) that we import with the exact same name in that file

bartvde avatar Apr 05 '23 16:04 bartvde

Have you tried to define "moduleResolution": "node" as per my previous entry? It has solved the problem for me.

crystalfp avatar Apr 06 '23 15:04 crystalfp

Have you tried to define "moduleResolution": "node" as per my previous entry? It has solved the problem for me.

yes we had that set up already in our tsconfig

bartvde avatar Apr 06 '23 16:04 bartvde

Sorry to ask @bartvde but also with the tsConfig addition to "madge" section the problem is still there?

crystalfp avatar Apr 12 '23 08:04 crystalfp

if I set the respective config in package.json for madge it seems to work, but not when I pass in the tsconfig which has moduleResolution set to node (--ts-config=tsconfig.json)

bartvde avatar Apr 13 '23 15:04 bartvde

Yes, there is something strange when you read a tsconfig.json compared to copying its content inside the madge section of package.json. For this I put a minimal tsconfig as per https://github.com/pahen/madge/issues/355#issuecomment-1475944946

crystalfp avatar Apr 13 '23 16:04 crystalfp