dpdm

repository·master·Indexed 21 days ago

https://github.com/acrazing/dpdm

A dependency parser and circular dependency detector for JavaScript and TypeScript projects. Version 4.3.0 provides a CLI and API to analyze source files, identify dependency graphs, detect circular references, and find unused files. It supports TypeScript path alias resolution via tsconfig, configuration files (e.g., dpdm.config.ts), and the ability to ignore specific dependencies using @dpdm-ignore comments.

Tokens
4.5K
Snippets
14
Records
19
Agent score
74%

What's inside dpdm

  1. Install DPDM

    master

    You can install DPDM either as a global command-line tool or as a development dependency in your project.

    Global installation (CLI):

    npm i -g dpdm
    # or via yarn
    yarn global add dpdm

    Local installation (as a module):

    npm i -D dpdm
    # or via yarn
    yarn add -D dpdm
    npm i -g dpdm
  2. Use DPDM via Command Line

    master

    DPDM provides a CLI to analyze dependencies and find circular references in JavaScript and TypeScript projects.

    Basic Usage

    Analyze a specific file:

    dpdm ./src/index.ts

    Common CLI Tasks

    • Print circular dependencies only:
      dpdm --no-warning --no-tree ./src/index.ts
    • Exit with a non-zero code if circular dependencies are found:
      dpdm --exit-code circular:1 ./src/index.ts
    • Ignore TypeScript type dependencies:
      dpdm -T ./src/index.ts
    • Find unused files: Provide a glob for files to check against and a starting entry point:
      dpdm --no-tree --no-warning --no-circular --detect-unused-files-from 'src/**/*.*' 'index.js'
    • Skip dynamic imports: Use --skip-dynamic-imports circular to ignore them only when parsing circular references, or --skip-dynamic-imports tree to ignore them when parsing source files.
      dpdm --skip-dynamic-imports circular index.js
    • Ignore specific imports in circular checks: Use --skip-imports with ISSUER:DEPENDENCY regex pairs.
      dpdm ./src/index.js --skip-imports 'src/a.js:.*' src/c.js:src/d.js
    • Analyze from a different working directory:
      dpdm --cwd ../other-project ./src/index.ts
    • Group output by package:
      dpdm --group-by-package './packages/*/src/index.ts'
    dpdm ./src/index.ts
  3. Ignore dependencies using source comments

    master

    You can manually tell DPDM to ignore a specific dependency by placing the @dpdm-ignore comment immediately before the dependency declaration. This works for:

    • import statements
    • export statements
    • require() calls
    • dynamic import() calls

    Example:

    // @dpdm-ignore
    import './intentional-cycle';
    // @dpdm-ignore
    import './intentional-cycle';
  4. Understand the Dependency and DependencyTree structures

    master

    dpdm represents the dependency graph using Dependency objects and a DependencyTree.

    Dependency

    Each Dependency object describes a single link in the graph:

    • issuer: The file that is making the import.
    • request: The import string/path used in the source code.
    • kind: The type of dependency (from DependencyKind).
    • id: The resolved filename or a shortened version.
      • If id === null, the dependency could not be resolved.
      • If tree[id] === null, the dependency was ignored.

    DependencyTree

    A DependencyTree is a Record<string, ReadonlyArray<Dependency> | null>. The keys are the file IDs, and the values are arrays of Dependency objects representing what that file imports. A null value indicates the file was ignored.

  5. Configure DPDM with a config file

    master

    DPDM automatically searches for configuration files in the working directory. Supported filenames include:

    • dpdm.config.ts
    • dpdm.config.mts
    • dpdm.config.cts
    • dpdm.config.mjs
    • dpdm.config.cjs
    • dpdm.config.js
    • dpdm.config.json

    CLI options will override values set in the config file.

    Example dpdm.config.ts:

    import { defineConfig } from 'dpdm';
    
    export default defineConfig({
      files: ['./src/index.ts'],
      exitCode: 'circular:1',
      transform: true,
      warning: false,
    });
    // dpdm.config.ts
    import { defineConfig } from 'dpdm';
    
    export default defineConfig({
      files: ['./src/index.ts'],
      exitCode: 'circular:1',
      transform: true,
      warning: false,
    });
    
    // Run via CLI
    // dpdm
  6. Use the dpdm CLI to analyze dependencies

    master

    dpdm is a command-line tool used to analyze file dependencies, detect circular dependencies, and identify unused files in a project. You can provide file paths or globs as positional arguments to specify the entry points for analysis.

    Basic Usage

    dpdm src/index.ts

    Key Features

    • Dependency Tree: Prints a visual representation of the dependency tree to stdout.
    • Circular Dependency Detection: Identifies and lists circular import paths.
    • Unused File Detection: When provided with a glob via --detect-unused-files-from, it identifies files that are not part of the dependency tree.
    • Warnings: Reports missing imports or other dependency issues.
    • JSON Output: Export the entire analysis (entries, tree, and circulars) to a JSON file using --output.
    dpdm [files...]
  7. Use DPDM as a package (API)

    master

    You can import DPDM functions directly into your application to programmatically analyze dependency trees and circular dependencies.

    Core API Functions

    • parseDependencyTree(entries, options): Parses dependencies for the provided glob entries. Returns a Promise<DependencyTree>.
    • parseCircular(tree): Parses circular dependencies from a DependencyTree. Returns an array of circular dependency paths (string[][]).
    • prettyCircular(circulars): Formats circular dependencies for readable output.
    • defineConfig(config): Helper to define configuration objects.
    • groupDependencyTreeByPackage(tree, context): Groups a dependency tree by the nearest package.json.

    Data Structures

    • DependencyTree: A Record<string, Dependency[] | null> where the key is the file ID and the value is its dependencies. If a file is ignored, its value is null.
    • Dependency: Represents an edge in the graph:
      • issuer: The file initiating the import.
      • request: The requested module path.
      • kind: The DependencyKind (e.g., StaticImport, DynamicImport, CommonJS).
      • id: The shortened, resolved filename (null if unresolvable).

    Example Usage

    import {
      defineConfig,
      parseDependencyTree,
      parseCircular,
      prettyCircular,
    } from 'dpdm';
    
    parseDependencyTree('./index', {
      /* options */
    }).then((tree) => {
      const circulars = parseCircular(tree);
      console.log(prettyCircular(circulars));
    });
    import {
      defineConfig,
      parseDependencyTree,
      parseCircular,
      prettyCircular,
    } from 'dpdm';
    
    parseDependencyTree('./index', {
      /* options, see below */
    }).then((tree) => {
      const circulars = parseCircular(tree);
      console.log(prettyCircular(circulars));
    });
  8. Configure dpdm via the Config interface

    master

    The Config interface defines the options available when using dpdm as a package or via its configuration surface. It allows you to control file selection, directory context, dependency parsing behavior, and output formatting.

    Key configuration areas:

    • File Selection: Use files to specify entry points, extensions for file types, and include/exclude (RegExp or string) to filter files.
    • Parsing Behavior:
      • tree: Set to true to ignore dynamic imports when parsing source files.
      • circular: Set to true to ignore dynamic imports when parsing circular references.
      • skipDynamicImports: Can be set to 'tree' or 'circular' to specifically target which phase ignores dynamic imports.
      • transform: Boolean to enable/disable transformation.
    • Output & Reporting:
      • output: Path to save results.
      • warning: Boolean to enable/disable warnings.
      • progress: Boolean to show progress.
      • exitCode: Specify the exit code behavior.
    • Filtering & Warnings:
      • ignoreMissWarnings, ignoreSkipWarnings, and ignoreMissWarning/ignoreSkipWarning allow you to suppress specific warning patterns using RegExp or strings.
    • Dependency Management:
      • skipImports: Array of strings to skip specific imports.
      • groupByPackage: Boolean to group dependencies by package.
    const config: Config = {
      files: ['./src/index.ts'],
      cwd: process.cwd(),
      extensions: ['.ts', '.js'],
      include: /src\//,
      exclude: /node_modules/,
      tree: true,
      skipDynamicImports: 'tree',
      output: './dependency-report.json'
    };
  9. Reference: DPDM CLI Options

    master

    The following options are available for the dpdm command line interface:

    OptionDescription
    files (positional)The file paths or globs to analyze.
    --versionShow version number.
    --config <path>The config file path. Default searches dpdm.config.* in cwd.
    --context <path>The context directory to shorten paths. Default is cwd.
    --cwd <path>The working directory used to match files and resolve relative paths.
    --extensions, --ext <list>Comma separated extensions to resolve. Default: .ts,.tsx,.mjs,.js,.jsx,.json.
    --js <list>Comma separated extensions indicating the file is JS-like. Default: .ts,.tsx,.mjs,.js,.jsx.
    --include <regexp>Included filenames regexp. Default: .*.
    --exclude <regexp>Excluded filenames regexp. Set to empty string to include all. Default: node_modules.
    -o, --output <path>Output JSON to file.
    --treePrint tree to stdout. Default: true.
    --circularPrint circular dependencies to stdout. Default: true.
    --warningPrint warnings to stdout. Default: true.
    --tsconfig <path>The tsconfig path used for resolving path aliases. Supports project references.
    -T, --transformTransform TypeScript modules to JavaScript before analysis (allows omitting type dependencies). Default: false.
    --exit-code <CASE:CODE>Exit with specified code. CASE must be circular. CODE is integer 0-128. e.g., --exit-code circular:1.
    --progressShow progress bar. Default: true.
    --detect-unused-files-from <glob>Glob used for finding unused files.
    --skip-dynamic-imports <tree|circular>Skip parsing import(...) statements.
    --skip-imports <array>Skip import edges from circular checks. Values are ISSUER:DEPENDENCY regex pairs.
    --ignore-miss-warning <array>Ignore missing warnings matching specified regex.
    --ignore-skip-warning <array>Ignore skip warnings matching specified regex.
    --group-by-packagePrint dependencies and circulars grouped by nearest package.json.
    -h, --helpShow help.
  10. Skip specific imports in circular checks

    master

    If you have known circular dependencies that you want to ignore during the circularity check, use the --skip-imports flag.

    Values must be provided as ISSUER:DEPENDENCY pairs, where both parts are relative paths or identifiers that can be resolved. You can provide multiple pairs separated by commas.

    Example: To skip the circular edge between src/a.ts and src/b.ts:

    dpdm --skip-imports src/a.ts:src/b.ts src/index.ts
  11. Configure circular dependency exit codes

    master

    You can instruct dpdm to exit with a specific non-zero exit code if circular dependencies are detected. This is useful for CI/CD pipelines to fail a build when circularity is introduced.

    The --exit-code flag accepts a format of CASE:CODE. Currently, only the circular case is supported.

    Example: To exit with code 1 if circular dependencies are found:

    dpdm --exit-code circular:1 src/index.ts
  12. Configure dpdm using defineConfig()

    master

    When creating a configuration file, use the defineConfig function to provide type safety and ensure your configuration object adheres to the expected Config schema. This is a common pattern in modern TypeScript-based tools to enable IDE autocompletion.

    import { defineConfig } from 'dpdm';
    
    export default defineConfig({
      // your configuration options here
    });