@octokit/app
Advanced tools
Comparing version 1.0.0 to 1.1.0
module.exports = App | ||
const getCache = require('./lib/get-cache') | ||
const getInstallationAccesToken = require('./lib/get-installation-access-token') | ||
const getSignedJsonWebToken = require('./lib/get-signed-json-web-token') | ||
const getInstallationAccesToken = require('./lib/get-installation-access-token') | ||
function App ({ id, privateKey }) { | ||
function App ({ id, privateKey, cache }) { | ||
const state = { | ||
id, | ||
privateKey | ||
privateKey, | ||
cache: cache || getCache() | ||
} | ||
@@ -11,0 +13,0 @@ const api = { |
@@ -9,3 +9,10 @@ module.exports = getInstallationAccesToken | ||
function getInstallationAccesToken (state, { installationId }) { | ||
return request('POST /app/installations/:installation_id/access_tokens', { | ||
const token = state.cache.get(installationId) | ||
if (token) { | ||
return Promise.resolve(token) | ||
} | ||
return request({ | ||
method: 'POST', | ||
url: '/app/installations/:installation_id/access_tokens', | ||
installation_id: installationId, | ||
@@ -17,4 +24,6 @@ headers: { | ||
} | ||
}).then(response => { | ||
state.cache.set(installationId, response.data.token) | ||
return response.data.token | ||
}) | ||
.then(response => response.data.token) | ||
} |
@@ -6,3 +6,3 @@ { | ||
}, | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "GitHub Apps toolset for Node.js", | ||
@@ -31,3 +31,4 @@ "main": "index.js", | ||
"@octokit/request": "^2.1.2", | ||
"jsonwebtoken": "^8.3.0" | ||
"jsonwebtoken": "^8.3.0", | ||
"lru-cache": "^5.1.1" | ||
}, | ||
@@ -37,9 +38,10 @@ "devDependencies": { | ||
"coveralls": "^3.0.2", | ||
"lolex": "^2.7.4", | ||
"lolex": "^3.0.0", | ||
"mocha": "^5.2.0", | ||
"nock": "^9.4.0", | ||
"nock": "^10.0.2", | ||
"nyc": "^13.1.0", | ||
"standard": "^12.0.1", | ||
"semantic-release": "^15.12.1" | ||
"semantic-release": "^15.12.1", | ||
"simple-mock": "^0.8.0", | ||
"standard": "^12.0.1" | ||
} | ||
} |
@@ -6,3 +6,3 @@ # app.js | ||
[![@latest](https://img.shields.io/npm/v/@octokit/app.svg)](https://www.npmjs.com/package/@octokit/app) | ||
[![Build Status](https://travis-ci.org/octokit/app.js.svg?branch=master)](https://travis-ci.org/octokit/app.js) | ||
[![Build Status](https://travis-ci.com/octokit/app.js.svg?branch=master)](https://travis-ci.com/octokit/app.js) | ||
[![Coverage Status](https://coveralls.io/repos/github/octokit/app.js/badge.svg)](https://coveralls.io/github/octokit/app.js) | ||
@@ -44,3 +44,3 @@ [![Greenkeeper](https://badges.greenkeeper.io/octokit/app.js.svg)](https://greenkeeper.io/) | ||
Once you have authenticated as a GitHub App, you can use that in order to request an installation access token. Calling `requestToken()` automatically performs the app authentication for you. This token is scoped for your specific app and expires after an hour. See also the [GitHub Developer Docs](https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation). | ||
Once you have authenticated as a GitHub App, you can use that in order to request an installation access token. Calling `requestToken()` automatically performs the app authentication for you. See also the [GitHub Developer Docs](https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation). | ||
@@ -69,4 +69,29 @@ ```js | ||
## Caching installation tokens | ||
Installation tokens expire after an hour. By default, `@octokit/app` is caching up to 15000 tokens simultaneously using [`lru-cache`](https://github.com/isaacs/node-lru-cache). You can pass your own cache implementation by passing `options.cache.{get,set}` to the constructor. | ||
```js | ||
const App = require('@octokit/app') | ||
const APP_ID = 1 | ||
const PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY-----\n...' | ||
const CACHE = {} | ||
const app = new App({ | ||
id: APP_ID, | ||
privateKey: PRIVATE_KEY, | ||
cache: { | ||
get (key) { | ||
return CACHE[key] | ||
}, | ||
set (key, value) { | ||
CACHE[key] = value | ||
} | ||
} | ||
}) | ||
``` | ||
## License | ||
[MIT](LICENSE) |
/* global describe, beforeEach, it */ | ||
const { expect } = require('chai') | ||
const lolex = require('lolex') | ||
const nock = require('nock') | ||
const lolex = require('lolex') | ||
const simple = require('simple-mock') | ||
@@ -42,3 +43,3 @@ const App = require('..') | ||
// Documentation: https://git.io/fASyr | ||
lolex.install({ now: 0, toFake: ['Date'] }) | ||
const clock = lolex.install({ now: 0, toFake: ['Date', 'setTimeout'] }) | ||
@@ -78,2 +79,96 @@ describe('app.js', () => { | ||
}) | ||
it('gets installation token from cache', () => { | ||
nock('https://api.github.com') | ||
.post('/app/installations/123/access_tokens') | ||
.reply(201, { | ||
token: 'foo' | ||
}) | ||
return app.getInstallationAccesToken({ installationId: 123 }) | ||
.then(token => { | ||
expect(token).to.equal('foo') | ||
return app.getInstallationAccesToken({ installationId: 123 }) | ||
}) | ||
.then(token => { | ||
expect(token).to.equal('foo') | ||
}) | ||
}) | ||
it('caches based on installation id', () => { | ||
nock('https://api.github.com') | ||
.post('/app/installations/123/access_tokens') | ||
.reply(201, { | ||
token: 'foo' | ||
}) | ||
.post('/app/installations/456/access_tokens') | ||
.reply(201, { | ||
token: 'bar' | ||
}) | ||
return app.getInstallationAccesToken({ installationId: 123 }) | ||
.then(token => { | ||
expect(token).to.equal('foo') | ||
return app.getInstallationAccesToken({ installationId: 456 }) | ||
}) | ||
.then(token => { | ||
expect(token).to.equal('bar') | ||
}) | ||
}) | ||
const oneHourInMs = 1000 * 60 * 60 | ||
it('request installation again after timeout', () => { | ||
const mock = nock('https://api.github.com') | ||
.post('/app/installations/123/access_tokens') | ||
.reply(201, { | ||
token: 'foo' | ||
}) | ||
.post('/app/installations/123/access_tokens') | ||
.reply(201, { | ||
token: 'bar' | ||
}) | ||
return app.getInstallationAccesToken({ installationId: 123 }) | ||
.then(token => { | ||
expect(token).to.equal('foo') | ||
return new Promise(resolve => { | ||
setTimeout(resolve, oneHourInMs) | ||
clock.tick(oneHourInMs) | ||
}) | ||
}) | ||
.then(() => { | ||
return app.getInstallationAccesToken({ installationId: 123 }) | ||
}) | ||
.then(token => { | ||
expect(token).to.equal('bar') | ||
expect(mock.pendingMocks()).to.deep.equal([]) | ||
}) | ||
}).timeout(oneHourInMs + 2000) | ||
it('supports custom cache', () => { | ||
nock('https://api.github.com') | ||
.post('/app/installations/123/access_tokens') | ||
.reply(201, { | ||
token: 'foo' | ||
}) | ||
const options = { | ||
id: APP_ID, | ||
privateKey: PRIVATE_KEY, | ||
cache: { | ||
get: simple.stub(), | ||
set: simple.stub() | ||
} | ||
} | ||
const appWithCustomCache = new App(options) | ||
return appWithCustomCache.getInstallationAccesToken({ installationId: 123 }) | ||
.then(token => { | ||
expect(options.cache.get.callCount).to.equal(1) | ||
expect(options.cache.set.callCount).to.equal(1) | ||
}) | ||
}) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18400
10
215
95
3
9
+ Addedlru-cache@^5.1.1
+ Addedlru-cache@5.1.1(transitive)
+ Addedyallist@3.1.1(transitive)