pahen / madge

Create graphs from your CommonJS, AMD or ES6 module dependencies
MIT License
8.71k stars 312 forks source link

Not able to call madge from esm codebase. #400

Closed unphased closed 5 months ago

unphased commented 5 months ago

Madge installed in my project as seen in package-lock:

    "node_modules/madge": {
      "version": "6.1.0",
      "resolved": "https://registry.npmjs.org/madge/-/madge-6.1.0.tgz",
      "integrity": "sha512-irWhT5RpFOc6lkzGHKLihonCVgM0YtfNUh4IrFeW3EqHpnt/JHUG3z26j8PeJEktCGB4tmGOOOJi1Rl/ACWucQ==",
      ...

Here is my code.

import * as madge from 'madge';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { l } from '../log';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const isProgramLaunchContext = () => {
  return fileURLToPath(import.meta.url) === process.argv[1];
}

// Which other source files depend on these provided ones?
export const computeDependents = (srcFiles: string[]) => {
  // need to grab actual typescript source location
  let projectDir = path.resolve(__dirname, '..')
  if (projectDir.split('/').pop() === 'build') {
    projectDir = path.resolve(projectDir, '..', '..', 'src');
  }
  l('projectDir', projectDir);

  madge(projectDir).then((res) => {
    console.log('dependents:', srcFiles.map(res.depends));
  });
};

isProgramLaunchContext() && (async () => {
  computeDependents(process.argv.slice(2));
})();

Running it leads to

❯ npx tsx src/project/deps.ts project/deps.ts
/Users/me/project/src/project/deps.ts:22
  madge(projectDir).then((res) => {
  ^

TypeError: madge is not a function
    at computeDependents (/Users/me/project/src/project/deps.ts:22:3)
    at <anonymous> (/Users/me/project/src/project/deps.ts:29:3)
    at <anonymous> (/Users/me/project/src/project/deps.ts:30:1)
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:120:12)

I get this same thing if i compile it to js (targeting esm!) with babel first and launch it with node.

unphased commented 5 months ago

Since it seems like madge hasn't been converted to module...

I tried to load it this way:

// Import Madge using dynamic import syntax
const madgeModule = await import('madge');
const madge = madgeModule.default;

it doesn't look like it can work.

/Users/me/project/node_modules/madge/lib/api.js:130
                const tree = this.obj();
                                  ^

TypeError: Cannot read properties of undefined (reading 'obj')
    at depends (/Users/me/project/node_modules/madge/lib/api.js:130:21)
    at Array.map (<anonymous>)
    at file:///Users/me/project/build/project/deps.js:24:41

Node.js v21.5.0
unphased commented 5 months ago

Maybe i was going off of old documentation. But I was able to get it working via:

// Import Madge using dynamic import syntax
import * as path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const isProgramLaunchContext = () => {
  return fileURLToPath(import.meta.url) === process.argv[1];
}

if (isProgramLaunchContext()) {
  console.log('ok');
  (async () => {
    const madgeModule = await import('madge');
    const madge = madgeModule.default;

    // Which other source files depend on these provided ones?
    const computeDependents = async (srcFiles: string[]) => {
      // need to grab actual typescript source location
      let projectDir = path.resolve(__dirname)
      if (projectDir.split('/').pop() === 'build') {
        projectDir = path.resolve(projectDir, '..', 'src');
      }
      console.log('projectDir', projectDir);

      const res = await madge(projectDir);
      console.log('res', res);
    };

    await computeDependents(process.argv.slice(2));
  })();
}

the insane thing i was trying before srcFiles.map(res.depends) can't work.