Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add findEmails utility function #1

Merged
merged 1 commit into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ node_modules

# ESLint
.eslintcache

# Build output
/dist
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/dist
.eslintcache
pnpm-lock.yaml
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,30 @@
[![npm](https://img.shields.io/npm/v/find-gh-commit-emails/latest)](https://www.npmjs.com/package/find-gh-commit-emails)
[![license: MIT](https://img.shields.io/npm/l/find-gh-commit-emails)](https://github.com/reifiedbeans/find-gh-commit-emails/blob/main/LICENSE)

A script to search for emails used by a given GitHub user.
Utilities for finding emails used by a given GitHub user.

## Usage

This package provides an executable that can be invoked directly.

```shell
npx find-gh-commit-emails <username>
```

A utility function is also provided for use in Node.js applications.

```javascript
import { findEmails } from "find-gh-commit-emails";

const username = "<username>";
const token = "[token]";
const options = {
includeCommitter: true,
};

const emailMap = await findEmails(username, token, options);
```

## License

Licensed under the [MIT License](https://github.com/reifiedbeans/find-gh-commit-emails/blob/main/LICENSE).
22 changes: 22 additions & 0 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env node
import { program } from "@commander-js/extra-typings";
import { findEmails } from "../lib/index.ts";

program
.name("find-gh-commit-emails")
.description(
"Search for emails used by a given GitHub user. " +
"Setting the GITHUB_TOKEN environment variable to a valid GitHub personal " +
"access token will enable searching in non-public repositories.",
)
.argument("username", "GitHub username to find emails for")
.option("--include-committer", "include committer email in results", false)
.configureHelp({ helpWidth: 80 })
.showHelpAfterError()
.action(async (username, opts) => {
const token = process.env["GITHUB_TOKEN"];
const emailsMap = await findEmails(username, token, opts);
console.log(JSON.stringify(emailsMap, null, 2));
});

program.parse(process.argv);
58 changes: 0 additions & 58 deletions index.js

This file was deleted.

51 changes: 51 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Octokit } from "octokit";

interface Options {
readonly includeCommitter?: boolean;
}

/**
* Find emails for a GitHub user
* @param username a GitHub username
* @param token a GitHub token
* @param opts additional options
*/
export async function findEmails(
username: string,
token?: string,
opts?: Options,
) {
const github = new Octokit({ auth: token });

const commitData = await github.paginate("GET /search/commits", {
q: `author:${username}`,
});

const emailMap = new Map<string, Set<string>>();

for (const entry of commitData) {
const repo = entry.repository.full_name;
const emails = [entry.commit.author.email];

if (opts?.includeCommitter && entry.commit.committer?.email) {
emails.push(entry.commit.committer.email);
}

for (const email of emails) {
let repos = emailMap.get(email);
if (!repos) {
repos = new Set();
emailMap.set(email, repos);
}
repos.add(repo);
}
}

const object: { [key: string]: string[] } = {};
for (const [email, repos] of emailMap) {
Object.assign(object, {
[email]: Array.from(repos),
});
}
return object;
}
19 changes: 12 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,26 @@
"license": "MIT",
"type": "module",
"files": [
"index.js"
"dist"
],
"main": "dist/lib/index.js",
"types": "dist/lib/index.d.ts",
"bin": {
"find-gh-commit-emails": "index.js"
"find-gh-commit-emails": "dist/bin/cli.js"
},
"engines": {
"node": ">=18"
},
"scripts": {
"build": "tsup",
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "eslint --cache --max-warnings=0 .",
"lint:fix": "eslint --fix --cache --max-warnings=0 .",
"prepack": "npm-run-all lint format:check"
"lint": "tsc && eslint --cache --max-warnings=0 .",
"lint:fix": "tsc && eslint --fix --cache --max-warnings=0 .",
"prepack": "npm-run-all build lint format:check"
},
"dependencies": {
"commander": "^12.1.0",
"@commander-js/extra-typings": "^12.1.0",
"octokit": "^4.0.2"
},
"devDependencies": {
Expand All @@ -36,7 +39,9 @@
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.3.2"
"prettier": "^3.3.2",
"tsup": "^8.1.0",
"typescript": "^5.5.3"
},
"publishConfig": {
"access": "public"
Expand Down
Loading