{"id":16861054,"url":"https://github.com/sergei-startsev/deps-walker","last_synced_at":"2025-09-15T02:30:45.670Z","repository":{"id":146292961,"uuid":"127050517","full_name":"sergei-startsev/deps-walker","owner":"sergei-startsev","description":"Walks through ESM dependencies graph. It's highly configurable ⚙","archived":false,"fork":false,"pushed_at":"2024-12-01T21:46:57.000Z","size":295,"stargazers_count":5,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-30T06:50:23.925Z","etag":null,"topics":["dependency-graph","deps-walker","esm","graph-traversal","imports","static-analysis","traverse"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sergei-startsev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-27T21:58:43.000Z","updated_at":"2024-09-02T21:11:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"d910b4f5-f456-40a1-948d-a015ccfc98c9","html_url":"https://github.com/sergei-startsev/deps-walker","commit_stats":{"total_commits":95,"total_committers":3,"mean_commits":"31.666666666666668","dds":0.5789473684210527,"last_synced_commit":"14f0915bbf25cacd56427869c0616a8f600bbe0f"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergei-startsev%2Fdeps-walker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergei-startsev%2Fdeps-walker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergei-startsev%2Fdeps-walker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergei-startsev%2Fdeps-walker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sergei-startsev","download_url":"https://codeload.github.com/sergei-startsev/deps-walker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233063431,"owners_count":18619381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency-graph","deps-walker","esm","graph-traversal","imports","static-analysis","traverse"],"created_at":"2024-10-13T14:28:59.496Z","updated_at":"2025-01-08T16:48:59.629Z","avatar_url":"https://github.com/sergei-startsev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# deps-walker\n\n[Graph traversal](https://en.wikipedia.org/wiki/Graph_traversal) to walk through ESM dependency graph for further static analysis. The traversal algorithm is classified as [Breadth-first search (BFS)](https://en.wikipedia.org/wiki/Breadth-first_search).\n\n## Install\n\n`$ npm install deps-walker`\n\n## Usage\n\nHere is an example of an entry point module `entry.js` with its dependencies, which in turn depend on their dependencies, which in turn depend on...\n\n```js\n//------ entry.js ------\nimport a from './a.js';\nimport b from './b.js';\n\n//------ a.js ------\nimport b from './b.js';\nimport c from './c.js';\nimport d from './d.js';\n\n//------ c.js ------\nimport d from './d.js';\n\n//------ d.js ------\nimport b from './b.js';\n```\n\nIn other words:\n\n```\nentry.js -\u003e a.js\nentry.js -\u003e b.js\na.js -\u003e b.js\na.js -\u003e c.js\na.js -\u003e d.js\nc.js -\u003e d.js\nd.js -\u003e b.js\n```\n\n\u003cp align='center'\u003e\n  \u003cimg alt='dependency graph'  width='400' src='./dependency-graph.png'\u003e\n\u003c/p\u003e\n\n`deps-walker` is used to traverse `entry.js` dependency graph:\n\n```js\nconst walk = require('deps-walker')();\n\nwalk('entry.js', (err, data) =\u003e {\n  if (err) {\n    // catch any errors...\n    return;\n  }\n  const { filePath, dependencies } = data;\n  // analyse module dependencies\n});\n```\n\nThe dependencies are traversed in the following order:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt='Breadth-first search traverse' width='400' src=\"./bfs.png\"\u003e\n\u003c/p\u003e\n\n#### Async/await API\n\n`deps-walker` support async/await API, it can be used to await traverse completion:\n\n```js\nasync function traverse() {\n  await walk('entry.js', (err, data) =\u003e {\n    /*...*/\n  });\n  console.log('Traverse is completed');\n}\n```\n\n#### Multiple entry points\n\n`deps-walker` supports multiple roots:\n\n```js\nwalk(['entry1.js', 'entry2.js', 'entry3.js'], (err, data) =\u003e {\n  /*...*/\n});\n```\n\n### Parsers\n\n`deps-walker` uses [@babel/parser](https://www.npmjs.com/package/@babel/parser) with `sourceType: 'module'` option by default. You can specify any other available [options](https://babeljs.io/docs/en/babel-parser.html#options):\n\n```js\nconst babelParse = require('deps-walker/lib/parsers/babel');\nconst walk = require('deps-walker')({\n  parse: (...args) =\u003e\n      babelParse(...args, {\n      // options\n      sourceType: 'module',\n      plugins: ['jsx', 'flow']\n    })\n});\n```\n\nor specify your own `parse` implementation:\n\n```js\nconst walk = require('deps-walker')({\n  parse: (code, filePath) =\u003e {\n    // parse implementation\n  }\n});\n```\n\n### Resolvers\n\nIt is not always obvious where `import x from 'module'` should look to find the file behind module, it depends on module resolution algorithms, which are specific for module bundlers, module syntax specs, etc.. `deps-walker` uses [resolve](https://www.npmjs.com/package/resolve) package, which implements NodeJS module resolution behavior. You may configure NodeJS `resolve` via available options:\n\n```js\nconst nodejsResolve = require('deps-walker/lib/resolvers/nodejs');\nconst walk = require('deps-walker')({\n  resolve: (...args) =\u003e\n    nodejsResolve(...args, {\n      // options\n      extensions: ['.js'],\n      paths: ['rootDir'],\n      moduleDirectory: 'node_modules'\n    })\n});\n```\n\nYou can also use other module resolution algorithms:\n\n```js\nconst walk = require('deps-walker')({\n  resolve: async (filePath, contextPath) =\u003e {\n    // resolve implementation\n  }\n});\n```\n\n### Ignoring\n\nYou may break traversal for some dependencies by specifying `ignore` function:\n\n```js\nconst walk = require('deps-walker')({\n  // ignore node_modules\n  ignore: filePath =\u003e /node_modules/.test(filePath)\n});\n```\n\n### Caching\n\nModule parsing and resolving can be resource intensive operation (CPU, I/O), cache allows you to speed up consecutive runs:\n\n```js\nconst cache = require('deps-walker/cache');\nconst walk = require('deps-walker')({ cache });\n//...\nawait cache.load('./cache.json');\nawait walk('entry.js', (err, data) =\u003e {\n  /*...*/\n});\nawait cache.save('./cache.json');\n```\n\n### Reading\n\nYou can also override the default file reader:\n\n```js\nconst fsPromises = require('fs').promises;\nconst read = _.memoize(filePath =\u003e fsPromises.readFile(filePath, 'utf8'));\nconst walk = require('deps-walker')({ read });\n```\n\n## License\n\n[MIT](https://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergei-startsev%2Fdeps-walker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsergei-startsev%2Fdeps-walker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergei-startsev%2Fdeps-walker/lists"}