When a programmer is developing a project, often they will pull in dependencies written by a third party to achieve a task. This is done because it tends to be easier to rely on a library which is the main focus of its developer, rather than reinventing the wheel just to build a car.

When a programmer explicitly declares a dependency in their project (such as via Maven or NPM), those are called direct dependencies because they are used directly by the developer. They’re often the dependencies the developer is thinking about when asked what third-party dependencies are in their project.

However, just as that developer is using dependencies to simplify their job, many times library developers will also use dependencies. A transitive dependency is one not imported directly into the project at hand, but instead imported by a direct dependency or another transitive dependency.

The depth of a dependency refers to how many layers removed a dependency is from your project. Different tools may use different standards for classifying dependency depths, and a dependency can have more than one depth because it can be depended on by multiple components in the graph.

Here’s an example of a package.json file from a NodeJS project with three direct dependencies, and the accompanying dependency graph:

{   "name": "Direct-vs-transitive-deps",   "version": "1.0.0",   "description": "",   "main": "index.js",   "scripts": {     "test": "echo \"Error: no test specified\" && exit 1"   },   "keywords": [],   "author": "",   "license": "ISC",   "dependencies": {     "color-convert": "^2.0.1",     "easy-fetch": "^0.0.1",     "imgclip": "^1.2.0"   } }

You may notice that each of these dependencies contains a ^ before the version number shown; these are dependency requirements, or dependency constraints. A dependency will always be pinned to a certain number, but you can also use constraint operators (like ^) to allow certain versions. Some other constraints might be >=1.3.5 or even more complex ones like >5.0.0, <=5.1.2. These allow the version resolution algorithm to pick potentially more up-to-date versions or minimize the unique version count of a single dependency.

      32 total deps, 3 direct  color-convert@2.0.1 | npm └─ color-name@1.1.4 | npm  easy-fetch@0.0.1 | npm ├─ q@1.5.1 | npm └─ node-fetch@1.7.3 | npm    ├─ is-stream@1.1.0 | npm    └─ encoding@0.1.13 | npm       └─ iconv-lite@0.6.3 | npm          └─ safer-buffer@2.1.2 | npm  imgclip@1.2.0 | npm ├─ tesseract.js@1.0.19 | npm │  ├─ tesseract.js-core@1.0.2 | npm │  ├─ png.js@0.2.1 | npm │  ├─ object-assign@4.1.1 | npm │  ├─ node-fetch@1.7.3 | npm │  │  ├─ is-stream@1.1.0 | npm │  │  └─ encoding@0.1.13 | npm │  │     └─ iconv-lite@0.6.3 | npm │  │        └─ safer-buffer@2.1.2 | npm │  ├─ level-js@2.2.4 | npm │  │  ├─ xtend@2.1.2 | npm │  │  │  └─ object-keys@0.4.0 | npm │  │  ├─ typedarray-to-buffer@1.0.4 | npm │  │  ├─ ltgt@2.2.1 | npm │  │  ├─ isbuffer@0.0.0 | npm │  │  ├─ idb-wrapper@1.7.2 | npm │  │  └─ abstract-leveldown@0.12.4 | npm │  │     └─ xtend@3.0.0 | npm │  ├─ jpeg-js@0.2.0 | npm │  ├─ isomorphic-fetch@2.2.1 | npm │  │  ├─ whatwg-fetch@3.6.2 | npm │  │  └─ node-fetch@1.7.3 | npm │  │     ├─ is-stream@1.1.0 | npm │  │     └─ encoding@0.1.13 | npm │  │        └─ iconv-lite@0.6.3 | npm │  │           └─ safer-buffer@2.1.2 | npm │  ├─ is-url@1.2.2 | npm │  └─ file-type@3.9.0 | npm ├─ progress@1.1.8 | npm ├─ copy-paste@1.5.3 | npm │  └─ iconv-lite@0.4.24 | npm │     └─ safer-buffer@2.1.2 | npm └─ commander@2.20.3 | npm

Dependency Graphs with FOSSA

At FOSSA, we treat the project as depth 0, so each direct dependency is treated as having a depth of 1. Whether the depth is 0-indexed or 1-indexed may vary depending on who’s generating the report, but as long as you know how to interpret the data, it doesn’t matter much.

In the above example, imgclip, easy-fetch, and color-convert are the three direct dependencies. In easy-fetch, we can see node-fetch is at depth 2. However, if we follow the graph from imgclip, we can see node-fetch is at depth 3 underneath tesseract. FOSSA shows the shallowest depth in reports since, generally, that’s the most relevant to a legal or security team.

You can pull a list of your project’s direct and transitive dependencies (up to five levels deep) by signing up for FOSSA’s free product. Once you’ve created an account, you can import your project either by integrating a VCS (like GitHub) or downloading our CLI. Then, once you’ve imported your project and run your first scan, you’ll see a list of dependencies. Visit our docs for more information on getting started.

Alternatively, if you’re interested in tracking dependencies more than five levels deep — and accessing our full range of open source license compliance and security features — please contact our team, and we’ll be happy to walk you through a custom demo.