{"id":10763,"library":"dpdm","title":"DPDM: Dependency Analyzer","description":"dpdm is a robust static dependency analyzer designed for JavaScript and TypeScript projects. It efficiently identifies circular dependencies, detects unused files, and generates comprehensive dependency trees. Currently at stable version 4.0.1, the library maintains a relatively frequent release cadence, often aligning minor versions with updates to TypeScript and Node.js to ensure compatibility with modern language features. Key differentiators include its complete support for both CommonJS and ESM module systems, comprehensive TypeScript features such as path mapping resolution and the ability to ignore type-only dependencies, and a lightweight architecture that leverages the official TypeScript compiler for parsing. It aims to provide stable and consistent output, addressing inconsistencies found in alternative tools like `madge` when analyzing complex TypeScript projects.","status":"active","version":"4.0.1","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/acrazing/dpdm","tags":["javascript","circular","dependency","dependencies","detect","static","JavaScript","TypeScript","typescript"],"install":[{"cmd":"npm install dpdm","lang":"bash","label":"npm"},{"cmd":"yarn add dpdm","lang":"bash","label":"yarn"},{"cmd":"pnpm add dpdm","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Used internally by dpdm for parsing all modules. Compatibility with the project's TypeScript version is crucial.","package":"typescript","optional":false}],"imports":[{"note":"The primary API function for programmatically analyzing dependencies. Prefer ESM imports.","wrong":"const { analyze } = require('dpdm');","symbol":"analyze","correct":"import { analyze } from 'dpdm';"},{"note":"Type definition for the options object passed to the `analyze` function.","symbol":"AnalyzeOptions","correct":"import type { AnalyzeOptions } from 'dpdm';"},{"note":"Type definition for the analysis result object returned by the `analyze` function.","symbol":"DpdmResult","correct":"import type { DpdmResult } from 'dpdm';"}],"quickstart":{"code":"import { analyze } from 'dpdm';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nconst projectRoot = process.cwd();\nconst srcDir = path.join(projectRoot, 'src');\n\n// Create dummy files for demonstration\nfs.mkdirSync(srcDir, { recursive: true });\nfs.writeFileSync(path.join(srcDir, 'a.ts'), 'import { b } from \"./b\"; export const a = b + 1;');\nfs.writeFileSync(path.join(srcDir, 'b.ts'), 'import { c } from \"./c\"; export const b = c + 1;');\nfs.writeFileSync(path.join(srcDir, 'c.ts'), 'import { a } from \"./a\"; export const c = a + 1;'); // Circular dependency\nfs.writeFileSync(path.join(srcDir, 'd.ts'), 'export const d = 4;'); // Unused file\n\nasync function runAnalysis() {\n  try {\n    const result = await analyze([path.join(srcDir, 'a.ts')], {\n      context: projectRoot,\n      exclude: 'node_modules',\n      circular: true,\n      tree: true,\n      detectUnusedFilesFrom: path.join(srcDir, '**/*.*')\n    });\n\n    console.log('Analysis completed:');\n    if (result.circular.length > 0) {\n      console.log('Circular dependencies found:', result.circular);\n    } else {\n      console.log('No circular dependencies found.');\n    }\n    if (result.unused.length > 0) {\n      console.log('Unused files found:', result.unused);\n    }\n    console.log('Full dependency tree (truncated for brevity):', Object.keys(result.tree).slice(0, 5));\n  } catch (error) {\n    console.error('Analysis failed:', error);\n  } finally {\n    // Clean up dummy files\n    fs.rmSync(srcDir, { recursive: true, force: true });\n  }\n}\n\nrunAnalysis();\n","lang":"typescript","description":"This quickstart demonstrates how to use `dpdm` programmatically to analyze a project for circular dependencies and unused files, showing basic configuration and result handling."},"warnings":[{"fix":"Upgrade your Node.js runtime environment to version 20 or newer. Use `nvm` or `volta` to manage Node.js versions if needed.","message":"Version 4.0.1 and subsequent versions require Node.js version 20 or greater to run. Older Node.js environments will not be supported.","severity":"breaking","affected_versions":">=4.0.1"},{"fix":"Ensure that your project's TypeScript version is compatible with the dpdm version you are using. Check dpdm's release notes for the supported TypeScript version in each major/minor release.","message":"dpdm closely tracks TypeScript versions due to its internal parsing mechanism. Using dpdm with a significantly older or newer TypeScript version in your project than what dpdm was built against (e.g., TS 5.6 for dpdm v3.15.0) can lead to parsing errors or incorrect analysis results.","severity":"gotcha","affected_versions":">=3.x"},{"fix":"Carefully choose between `circular` and `tree` values for `--skip-dynamic-imports` based on whether you want to exclude dynamic imports from only circularity checks or from the entire dependency graph analysis.","message":"The `--skip-dynamic-imports` CLI option (or `skipDynamicImports` API option) has two distinct behaviors: 'circular' only ignores dynamic imports when detecting circular references, while 'tree' ignores them during the initial source file parsing for the full dependency tree. Misunderstanding this can lead to incomplete analysis or unexpected results.","severity":"gotcha","affected_versions":">=3.13.0"},{"fix":"Always use `--exit-code circular:1` (or a similar pattern for other checks like unused files) in CI/CD environments to ensure that the build process fails if unwanted dependencies are detected.","message":"When using `dpdm` in a CI/CD pipeline, relying solely on its output to `stdout` might not integrate well with build failure conditions. The `--exit-code` option is crucial for making the pipeline fail if circular dependencies are found.","severity":"gotcha","affected_versions":">=3.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Upgrade Node.js to version 20 or newer using `nvm install 20 && nvm use 20` or by updating your Node.js distribution.","cause":"The installed version of Node.js is older than the minimum required by dpdm v4.x.","error":"Error: dpdm requires Node.js v20.x or higher. You are using v18.x.x."},{"fix":"Double-check the file paths and glob patterns specified in your dpdm command or API call. Ensure they are relative to the `--context` or `context` option, or are absolute paths.","cause":"The entry file(s) or glob pattern provided to dpdm do not exist or are incorrect.","error":"ENOENT: no such file or directory, stat '/path/to/your/project/src/index.ts'"},{"fix":"Update dpdm to its latest version, or ensure your project's `tsconfig.json` `compilerOptions.target` and `moduleResolution` settings are standard and well-formed. Verify that the TypeScript version your project uses is compatible with the dpdm version's tested TS version.","cause":"This often indicates a TypeScript version mismatch where dpdm's internal parser struggles with the project's TypeScript syntax or configuration, or an issue with path mapping resolution.","error":"TypeError: Cannot read properties of undefined (reading 'resolvedModules') at getDependenciesOfSourceFile"},{"fix":"Verify your `tsconfig.json` includes correct `compilerOptions.baseUrl` and `compilerOptions.paths` if you are using path aliases. Ensure `--extensions` (or `extensions` in API) includes all relevant file types for resolution (e.g., `.ts,.tsx,.js,.jsx`).","cause":"dpdm could not resolve an import path, possibly due to missing `baseUrl` or `paths` configuration in `tsconfig.json`, or an incorrect `--extensions` setting.","error":"Error: Unable to resolve module: 'src/components/button' in '/path/to/project/src/pages/home.ts'"}],"ecosystem":"npm"}