Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/github-username
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d2c8fc6c694e4a1ced1646343a5dfc4e8ffbecf2
Choose a base ref
...
head repository: sindresorhus/github-username
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a1c09b8782b364570986903dec06fbc00b3730d8
Choose a head ref
  • 9 commits
  • 11 files changed
  • 4 contributors

Commits on Apr 15, 2019

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    fe861db View commit details
  2. Meta tweaks

    sindresorhus committed Apr 15, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1de6d8f View commit details
  3. 5.0.0

    sindresorhus committed Apr 15, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    0fbe5a7 View commit details

Commits on May 28, 2019

  1. Create funding.yml

    sindresorhus authored May 28, 2019
    Copy the full SHA
    929895f View commit details

Commits on Jun 2, 2019

  1. Copy the full SHA
    c353a93 View commit details
  2. 5.0.1

    sindresorhus committed Jun 2, 2019
    Copy the full SHA
    2640b0d View commit details

Commits on Dec 23, 2020

  1. Migrate to @octokit/rest (#12)

    Richienb authored Dec 23, 2020
    Copy the full SHA
    9e95e07 View commit details
  2. Require Node.js 10

    sindresorhus committed Dec 23, 2020
    Copy the full SHA
    1c1a48c View commit details
  3. 6.0.0

    sindresorhus committed Dec 23, 2020
    Copy the full SHA
    a1c09b8 View commit details
Showing with 135 additions and 109 deletions.
  1. +1 −2 .gitattributes
  2. +3 −0 .github/funding.yml
  3. +22 −0 .github/workflows/main.yml
  4. +0 −5 .travis.yml
  5. +20 −0 index.d.ts
  6. +29 −41 index.js
  7. +6 −0 index.test-d.ts
  8. +1 −1 license
  9. +38 −38 package.json
  10. +8 −15 readme.md
  11. +7 −7 test.js
3 changes: 1 addition & 2 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
* text=auto
*.js text eol=lf
* text=auto eol=lf
3 changes: 3 additions & 0 deletions .github/funding.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
github: sindresorhus
open_collective: sindresorhus
custom: https://sindresorhus.com/donate
22 changes: 22 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI
on:
- push
- pull_request
jobs:
test:
name: Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 10
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
5 changes: 0 additions & 5 deletions .travis.yml

This file was deleted.

20 changes: 20 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
Get the GitHub username from an email address if the email can be found in any commits on GitHub.
@param email - Email address for the user of whom you want the username.
@param token - GitHub [personal access token](https://github.com/settings/tokens/new).
@returns The username for the `email` or `undefined` if it cannot be found.
@example
```
import githubUsername = require('github-username');
(async () => {
console.log(await githubUsername('sindresorhus@gmail.com'));
//=> 'sindresorhus'
})();
```
*/
declare function githubUsername(email: string, token?: string): Promise<string | undefined>;

export = githubUsername;
70 changes: 29 additions & 41 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,38 @@
'use strict';
const ghGot = require('gh-got');

function searchCommits(email, token) {
return ghGot('search/commits', {
token,
query: {
q: `author-email:${email}`,
sort: 'author-date',
// eslint-disable-next-line camelcase
per_page: 1
},
headers: {
accept: 'application/vnd.github.cloak-preview',
'user-agent': 'https://github.com/sindresorhus/github-username'
}
}).then(result => {
const data = result.body;

if (data.total_count === 0) {
throw new Error(`Couldn't find username for \`${email}\``);
}

return data.items[0].author.login;
const {Octokit} = require('@octokit/rest');

async function searchCommits(octokit, email) {
const {data} = await octokit.search.commits({
q: `author-email:${email}`,
sort: 'author-date',
// eslint-disable-next-line camelcase
per_page: 1
});

if (data.total_count === 0) {
throw new Error(`Couldn't find username for \`${email}\``);
}

return data.items[0].author.login;
}

module.exports = (email, token) => {
module.exports = async (email, token) => {
if (!(typeof email === 'string' && email.includes('@'))) {
return Promise.reject(new Error('Email required'));
throw new Error('Email required');
}

return ghGot('search/users', {
token,
query: {
q: `${email} in:email`
},
headers: {
'user-agent': 'https://github.com/sindresorhus/github-username'
}
}).then(result => {
const data = result.body;

if (data.total_count === 0) {
return searchCommits(email, token);
}

return data.items[0].login;
const octokit = new Octokit({
auth: token,
userAgent: 'https://github.com/sindresorhus/github-username'
});

const {data} = await octokit.search.users({
q: `${email} in:email`
});

if (data.total_count === 0) {
return searchCommits(octokit, email);
}

return data.items[0].login;
};
6 changes: 6 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import {expectType} from 'tsd';
import githubUsername = require('.');

expectType<Promise<string | undefined>>(
githubUsername('sindresorhus@gmail.com', 'deadbeef')
);
2 changes: 1 addition & 1 deletion license
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

76 changes: 38 additions & 38 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
{
"name": "github-username",
"version": "4.1.0",
"description": "Get a GitHub username from an email address",
"license": "MIT",
"repository": "sindresorhus/github-username",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=4"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js"
],
"keywords": [
"github",
"user",
"username",
"email",
"address",
"gh",
"git"
],
"dependencies": {
"gh-got": "^6.0.0"
},
"devDependencies": {
"ava": "*",
"xo": "*"
},
"xo": {
"esnext": true
}
"name": "github-username",
"version": "6.0.0",
"description": "Get a GitHub username from an email address",
"license": "MIT",
"repository": "sindresorhus/github-username",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"github",
"user",
"username",
"email",
"address",
"gh",
"git"
],
"dependencies": {
"@octokit/rest": "^18.0.6"
},
"devDependencies": {
"ava": "^2.4.0",
"tsd": "^0.14.0",
"xo": "^0.36.1"
}
}
23 changes: 8 additions & 15 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
# github-username [![Build Status](https://travis-ci.org/sindresorhus/github-username.svg?branch=master)](https://travis-ci.org/sindresorhus/github-username)
# github-username

> Get a GitHub username from an email address

## Install

```
$ npm install github-username
```


## Usage

```js
const githubUsername = require('github-username');

githubUsername('sindresorhus@gmail.com').then(username => {
console.log(username);
(async () => {
console.log(await githubUsername('sindresorhus@gmail.com'));
//=> 'sindresorhus'
});
})();
```


## API

### githubUsername(email, [token])
### githubUsername(email, token?)

Get the GitHub username from an email address if the email can be found in any commits on GitHub.

Returns a `Promise` for the username.
Returns a `Promise<string?>` with the username.

#### email

@@ -40,12 +39,6 @@ Type: `string`

GitHub [personal access token](https://github.com/settings/tokens/new).


## Related

- [github-username-cli](https://github.com/sindresorhus/github-username-cli) - CLI for this module


## License

MIT © [Sindre Sorhus](https://sindresorhus.com)
14 changes: 7 additions & 7 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import test from 'ava';
import m from './';
import githubUsername from '.';

test('gets GitHub username from email', async t => {
t.is(await m('sindresorhus@gmail.com'), 'sindresorhus');
t.is(await githubUsername('sindresorhus@gmail.com'), 'sindresorhus');
});

test('gets GitHub username from email using Commit Search API', async t => {
t.is(await m('markdotto@gmail.com'), 'mdo');
t.is(await githubUsername('markdotto@gmail.com'), 'mdo');
});

test('rejects when GitHub has no user for the email', async t => {
await t.throws(m('nogithubaccount@example.com'));
await t.throwsAsync(githubUsername('nogithubaccount@example.com'));
});

test('rejects when email is missing', async t => {
await t.throws(m());
await t.throwsAsync(githubUsername());
});

test('rejects when email is invalid', async t => {
await t.throws(m('sindresorhus_gmail.com'));
await t.throwsAsync(githubUsername('sindresorhus_gmail.com'));
});

test('rejects when email is not a string', async t => {
await t.throws(m(() => 'sindresorhus_gmail.com'));
await t.throwsAsync(githubUsername(() => 'sindresorhus_gmail.com'));
});