{"id":16351592,"url":"https://github.com/tomeraberbach/find-entry-points","last_synced_at":"2025-08-20T16:06:22.007Z","repository":{"id":57236232,"uuid":"270524081","full_name":"TomerAberbach/find-entry-points","owner":"TomerAberbach","description":"🚪 Find the entry points in a set of JavaScript files.","archived":false,"fork":false,"pushed_at":"2024-10-15T03:29:21.000Z","size":671,"stargazers_count":41,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-17T19:12:20.684Z","etag":null,"topics":["entrypoints","esm","graph","javascript","strongly-connected-components","tarjan-algorithm"],"latest_commit_sha":null,"homepage":"https://npm.im/find-entry-points","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomerAberbach.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"contributing.md","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":"2020-06-08T04:10:49.000Z","updated_at":"2024-10-15T03:29:26.000Z","dependencies_parsed_at":"2024-10-28T09:24:52.891Z","dependency_job_id":null,"html_url":"https://github.com/TomerAberbach/find-entry-points","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomerAberbach%2Ffind-entry-points","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomerAberbach%2Ffind-entry-points/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomerAberbach%2Ffind-entry-points/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomerAberbach%2Ffind-entry-points/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomerAberbach","download_url":"https://codeload.github.com/TomerAberbach/find-entry-points/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244717354,"owners_count":20498282,"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":["entrypoints","esm","graph","javascript","strongly-connected-components","tarjan-algorithm"],"created_at":"2024-10-11T01:23:18.335Z","updated_at":"2025-03-21T00:31:04.326Z","avatar_url":"https://github.com/TomerAberbach.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  find-entry-points\n\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://npmjs.org/package/find-entry-points\"\u003e\n    \u003cimg src=\"https://badgen.now.sh/npm/v/find-entry-points\" alt=\"version\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/TomerAberbach/find-entry-points/actions\"\u003e\n    \u003cimg src=\"https://github.com/TomerAberbach/find-entry-points/workflows/CI/badge.svg\" alt=\"CI\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=find-entry-points\"\u003e\n    \u003cimg src=\"https://badgen.net/bundlephobia/minzip/find-entry-points\" alt=\"minzip size\" /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  Find the entry points in a set of JavaScript files.\n\u003c/div\u003e\n\n## Install\n\n```sh\n$ npm i find-entry-points\n```\n\n## Huh?\n\n### Example 1\n\nGiven a sync or async iterable of paths to the JavaScript files with the\nfollowing dependencies between them (a directed arrow from `a.js` to `b.js`\nmeans `a.js` imports `b.js`):\n\n![](docs/example1.svg)\n\nThe `findEntryPoints` function would return `[['a.js']]` because `a.js` is the\nentry point of the above JavaScript library or application (it is not imported\nby any JavaScript file). The `findSingleEntryPoints` function would return\n`['a.js']`.\n\n### Example 2\n\nGiven a sync or async iterable of paths to the JavaScript files with the\nfollowing dependencies between them:\n\n![](docs/example2.svg)\n\nThe `findEntryPoints` function would return `[['a.js'], ['f.js'], ['g.js']]`\n(order not guaranteed) because `a.js`, `f.js`, and `g.js` are all not imported\nby any JavaScript file. Notice that it is possible to have a disconnected\ndependency graph. The `findSingleEntryPoints` function would return\n`['a.js', 'f.js', 'g.js']` (order not guaranteed).\n\n### Example 3\n\nGiven a sync or async iterable of paths to the JavaScript files with the\nfollowing dependencies between them:\n\n![](docs/example3.svg)\n\nThe `findEntryPoints` function would return `[['a.js'], ['g.js']]` (order not\nguaranteed). Notice that cycles are possible because imports are cached. The\n`findSingleEntryPoints` function would return `['a.js', 'g.js']` (order not\nguaranteed).\n\n### Example 4\n\nGiven a sync or async iterable of paths to the JavaScript files with the\nfollowing dependencies between them:\n\n![](docs/example4.svg)\n\nThe `findEntryPoints` function would return\n`[['a.js'], ['g.js', 'h.js', 'i.js']]` (order not guaranteed). Notice that this\nis the first example where an inner array contains more than one element. This\nis because `g.js`, `h.js`, and `i.js` are all valid entry points for their graph\ncomponent. The `findSingleEntryPoints` function would return `['a.js']` (order\nnot guaranteed).\n\n## Usage\n\nSuppose the JavaScript files with the following dependencies between them are\nall in a `src` directory and that `h.js` imports `i.js` via a dynamic import:\n\n![](docs/example4.svg)\n\n```js\nimport { findEntryPoints, findSingleEntryPoints } from 'find-entry-points'\nimport globby from 'globby'\nimport * as swc from '@swc/core'\n\n// `globby.stream` returns an async iterable of file paths\nconsole.log(await findEntryPoints(globby.stream('src/**/*.js')))\n//=\u003e [['src/a.js'], ['src/g.js', 'src/h.js', 'src/i.js']]\n\n// `findSingleEntryPoints` ignores cyclic entry points\nconsole.log(await findSingleEntryPoints(globby.stream('src/**/*.js')))\n// =\u003e ['src/a.js']\n\nconsole.log(\n  await findEntryPoints(globby.stream('src/**/*.js'), {\n    followDynamicImports: false\n  })\n)\n//=\u003e [['src/a.js'], ['src/i.js']]\n\nconsole.log(\n  await findSingleEntryPoints(globby.stream('src/**/*.js'), {\n    followDynamicImports: false\n  })\n)\n// =\u003e ['src/a.js', 'src/i.js']\n\n// Use the `transform` option to transform non-standard syntax\n// like JSX to standard ECMAScript so that imports can be parsed\nconsole.log(\n  await findEntryPoints(globby.stream('src/**/*.js'), {\n    transform: async ({ path, code }) =\u003e\n      (\n        await transform(code, {\n          filename: path,\n          jsc: { parser: { jsx: true } }\n        })\n      ).code\n  })\n)\n//=\u003e [['src/a.js'], ['src/g.js', 'src/h.js', 'src/i.js']]\n\nconsole.log(\n  await findSingleEntryPoints(globby.stream('src/**/*.js'), {\n    transform: async ({ path, code }) =\u003e\n      (\n        await transform(code, {\n          filename: path,\n          jsc: { parser: { jsx: true } }\n        })\n      ).code\n  })\n)\n//=\u003e ['src/a.js']\n\n// Use the `parseImports` option to parse imports yourself\nconsole.log(\n  await findEntryPoints(globby.stream('src/**/*.js'), {\n    parseImports: async ({ followDynamicImports, file }) =\u003e {\n      const { path, read } = file\n\n      // Read the file if you want\n      const code = await read()\n      const importedFilenames = yourFancyImportParser(code)\n\n      return importedFilenames\n    }\n  })\n)\n```\n\nSee\n[the commented type definitions](https://github.com/TomerAberbach/find-entry-points/blob/main/src/index.d.ts)\nfor clarification.\n\n## How?\n\nThe package uses\n[`parse-imports`](https://github.com/TomerAberbach/parse-imports) (another\npackage of mine) to construct a dependency graph, which is a\n[directed graph](\u003chttps://en.wikipedia.org/wiki/Graph_(discrete_mathematics)#Directed_graph\u003e),\nfrom the given set of JavaScript files. Then the package finds the\n[strongly connected components](https://en.wikipedia.org/wiki/Strongly_connected_component)\nof the dependency graph using\n[Tarjan's strongly connected components algorithm](https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm),\nand constructs a\n[directed acyclic graph from the strongly connected components](https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions:~:text=If%20each%20strongly%20connected%20component%20is,contains%20at%20least%20one%20directed%20cycle.).\nFinally, the package returns the strongly connected components corresponding to\nthe [vertices](\u003chttps://en.wikipedia.org/wiki/Vertex_(graph_theory)\u003e) with\n[in-degree](https://en.wikipedia.org/wiki/Directed_graph#Indegree_and_outdegree)\n1 in the new directed acyclic graph.\n\n## Contributing\n\nStars are always welcome!\n\nFor bugs and feature requests,\n[please create an issue](https://github.com/TomerAberbach/find-entry-points/issues/new).\n\nFor pull requests, please read the\n[contributing guidelines](https://github.com/TomerAberbach/find-entry-points/blob/main/contributing.md).\n\n## License\n\n[Apache 2.0](https://github.com/TomerAberbach/find-entry-points/blob/main/license)\n\nThis is not an official Google product.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomeraberbach%2Ffind-entry-points","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomeraberbach%2Ffind-entry-points","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomeraberbach%2Ffind-entry-points/lists"}