Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

github-base

Package Overview
Dependencies
Maintainers
2
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github-base - npm Package Compare versions

Comparing version 0.5.4 to 1.0.0

CHANGELOG.md

248

index.js
'use strict';
var use = require('use');
var utils = require('./lib/utils');
const use = require('use');
const utils = require('./lib/utils');

@@ -10,6 +10,6 @@ /**

* ```js
* var GitHub = require('github-base');
* var github = new GitHub(options);
* const GitHub = require('github-base');
* const github = new GitHub([options]);
* ```
*
* @name GitHub
* @param {Object} `options`

@@ -19,213 +19,159 @@ * @api public

function GitHub(options) {
if (!(this instanceof GitHub)) {
var proto = Object.create(GitHub.prototype);
GitHub.apply(proto, arguments);
return proto;
class GitHub {
constructor(options = {}) {
this.options = options;
use(this);
}
use(this);
this.defaults = utils.defaults(options);
}
/**
* GitHub prototype methods
*/
GitHub.prototype = {
constructor: GitHub,
/**
* Uses [simple-get][] to make a single request to the GitHub API, based on
* the provided settings. Supports any of the GitHub API VERBs:
* Uses [needle][] to make a request to the GitHub API. Supports the following verbs:
* `GET`, `PUT`, `POST`, `PATCH`, and `DELETE`. Takes a callback or returns a promise.
*
* - `GET`
* - `PUT`
* - `POST`
* - `DELETE`
* - `PATCH`
*
* ```js
* //example..request
* github.request('GET', '/user/orgs', function (err, res) {
* //=> array of orgs
* });
* // list all orgs for the authenticated user
* const auth = require('./local-private-auth-info');
* const github = new GitHub(auth);
* github.request('GET', '/user/orgs')
* .then(res => console.log(res.body));
* ```
* @name .request
* @param {String} `method` The http VERB to use
* @param {String} `url` GitHub API URL to use.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
request: function(method, path, options, cb) {
if (typeof options === 'function') {
return this.request.call(this, method, path, {}, options);
}
if (typeof cb !== 'function') {
throw new TypeError('expected callback to be a function');
}
utils.request(this.defaults(method, path, options), cb);
},
request(method, path, options) {
return utils.request(method, path, { ...this.options, ...options });
}
/**
* Makes a single `GET` request to the GitHub API based on the
* provided settings.
* Make a `GET` request to the GitHub API.
*
* ```js
* // get orgs for the authenticated user
* github.get('/user/orgs', function (err, res) {
* //=> array of orgs
* });
* // get a list of orgs for the authenticated user
* github.get('/user/orgs')
* .then(res => console.log(res.body));
*
* // get gists for the authenticated user
* github.get('/gists', function (err, res) {
* //=> array of gists
* });
* github.get('/gists')
* .then(res => console.log(res.body));
* ```
* @name .get
* @param {String} `path` path to append to the GitHub API URL.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
get: function(path, options, cb) {
this.request('GET', path, options, cb);
},
get(path, options) {
return this.request('GET', path, options);
}
/**
* Performs a request using [simple-get][], and then if necessary requests
* additional paged content based on the response. Data from all pages are
* concatenated together and buffered until the last page of data has been retrieved.
* Make a `DELETE` request to the GitHub API.
*
* ```js
* // get all repos for the authenticated user
* var url = '/user/repos?type=all&per_page=1000&sort=updated';
* github.paged(url, function(err, res) {
* console.log(res);
* });
* // un-follow someone
* github.delete('/user/following/:some_username', { some_username: 'whatever' })
* .then(res => {
* console.log('RESPONSE:', res);
* });
* ```
* @name .paged
* @param {String} `path` path to append to the GitHub API URL.
* @param {Function} `cb`
* @name .delete
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
paged: function(path, options, cb) {
if (typeof options === 'function') {
this.paged.call(this, path, {}, options);
return;
}
utils.paged(this.defaults('GET', path, options), cb);
},
delete(path, options) {
return this.request('DELETE', path, options);
}
/**
* Makes a single `DELETE` request to the GitHub API based on the
* provided settings.
* Make a `PATCH` request to the GitHub API.
*
* ```js
* // un-follow someone
* github.del('/user/following/someoneelse', function(err, res) {
* console.log(res);
* });
* // update a gist
* const fs = require('fs');
* const options = { files: { 'readme.md': { content: fs.readFileSync('README.md', 'utf8') } } };
* github.patch('/gists/bd139161a425896f35f8', options)
* .then(res => {
* console.log('RESPONSE:', res);
* });
* ```
* @name .del
* @param {String} `path` path to append to the GitHub API URL.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @name .patch
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
del: function(path, options, cb) {
this.request('DELETE', path, options, cb);
},
patch(path, options) {
return this.request('PATCH', path, options);
}
/**
* Makes a single `PATCH` request to the GitHub API based on the
* provided settings.
* Make a `POST` request to the GitHub API.
*
* ```js
* // update a gist
* var fs = require('fs');
* var opts = {files: {'readme.md': { content: '# My Readme...' }}};
* github.patch('/gists/bd139161a425896f35f8', opts, function(err, res) {
* console.log(err, res);
* });
* // create a new repository
* github.post('/user/repos', { name: 'new-repo-name' })
* .then(res => {
* console.log('RESPONSE:', res);
* });
* ```
* @name .patch
* @param {String} `path` path to append to the GitHub API URL.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @name .post
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
patch: function(path, options, cb) {
this.request('PATCH', path, options, cb);
},
post(path, options) {
return this.request('POST', path, options);
}
/**
* Makes a single `POST` request to the GitHub API based on the
* provided settings.
* Make a `PUT` request to the GitHub API.
*
* ```js
* // create a new repo
* var opts = { name: 'new-repo-name' };
* github.post('/user/repos', opts, function(err, res) {
* console.log(res);
* });
* // follow someone
* github.put('/user/following/jonschlinkert')
* .then(res => {
* console.log('RESPONSE:', res);
* });
* ```
* @name .post
* @param {String} `path` path to append to the GitHub API URL.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @name .put
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
post: function(path, options, cb) {
this.request('POST', path, options, cb);
},
put(path, options) {
return this.request('PUT', path, options);
}
/**
* Makes a single `PUT` request to the GitHub API based on the provided
* settings.
* Recursively make GET requests until all pages of records are returned.
*
* ```js
* // follow someone
* github.put('/user/following/jonschlinkert', function(err, res) {
* console.log(res);
* });
* // get all repos for the authenticated user
* github.paged('/user/repos?type=all&per_page=1000&sort=updated')
* .then(res => console.log(res.pages))
* .catch(console.error)
* ```
* @name .put
* @param {String} `path` path to append to the GitHub API URL.
* @param {Options} `options` Request options.
* @param {Function} `cb`
* @name .paged
* @param {String} `path` The path to append to the base GitHub API URL.
* @param {Options} `options` Request [options](#options).
* @api public
*/
put: function(path, options, cb) {
this.request('PUT', path, options, cb);
paged(path, options, next) {
if (typeof options === 'function') {
next = options;
options = null;
}
return utils.paged('GET', path, { ...this.options, ...options, next });
}
};
}
/**
* Static method for inheriting the prototype and static methods of the `Base` class.
* This method greatly simplifies the process of creating inheritance-based applications.
* See [static-extend][] for more details.
*
* ```js
* var GitHub = require('github-base');
* function MyApp() {
* GitHub.call(this);
* }
* GitHub.extend(MyApp);
* ```
* @name #extend
* @param {Function} `Ctor` constructor to extend
* @api public
*/
utils.define(GitHub, 'extend', utils.staticExtend(GitHub));
/**
* Expose `GitHub`

@@ -232,0 +178,0 @@ */

'use strict';
var utils = module.exports;
const qs = require('qs');
const url = require('url');
const get = require('get-value');
const needle = require('needle');
const paged = require('paged-request');
const parseLink = require('parse-link-header');
const defaultHeaders = {
accept: 'application/json',
'user-agent': 'https://github.com/jonschlinkert/github-base'
};

@@ -9,11 +18,12 @@ /**

utils.define = require('define-property');
utils.extend = require('extend-shallow');
utils.isBuffer = require('is-buffer');
utils.merge = require('mixin-deep');
utils.omit = require('object.omit');
utils.parseLink = require('parse-link-header');
utils.simpleGet = require('simple-get');
utils.staticExtend = require('static-extend');
exports.request = function(method, path, options) {
const defaults = exports.defaults({});
const opts = Object.assign({}, defaults(method, path, options));
let data = /^(put|patch|post)$/i.test(opts.method) ? options : null;
if (data) data = JSON.stringify(sanitize(data, opts.params));
return needle(opts.method, opts.url, data, opts)
.then(res => result(res, data, opts, options));
};
/**

@@ -23,97 +33,69 @@ * Recursive walk over paged content

utils.request = function(options, cb) {
options = options || {};
var opts = utils.extend({}, options, {json: false});
exports.paged = function(method, path, options) {
const defaults = exports.defaults({});
const opts = Object.assign({}, defaults(method, path, options));
utils.simpleGet.concat(opts, function(err, stream, data) {
if (err) {
if (stream && stream.statusCode === 204) {
cb(err, null, stream);
return;
}
cb(err);
return;
function nextPage(_url, res, acc) {
if (typeof opts.next === 'function') {
opts.next(_url, sanitize(res), sanitize(acc));
}
if (opts.paged === true || options.json !== false) {
if (utils.isBuffer(data)) {
data = data.toString();
}
let page;
if (res.headers.link && (page = parseLink(res.headers.link))) {
return page.next ? page.next.url : null;
}
}
if (typeof data === 'string' && data.trim()) {
data = JSON.parse(data);
}
}
cb(null, data, stream);
});
return paged(opts.url, opts, nextPage)
.then(res => result(res, options, opts, options))
.then(res => sanitize(res));
};
/**
* Recursive walk over paged content
* Normalize request options object, request body, headers and related properties
* to use for GitHub API requests.
*
* @param {Object} `appOptions` Options on the instance of github-base.
* @return {Function} Returns a function that takes a request method name, the URL to expand, and method options.
*/
utils.paged = function(options, cb) {
var opts = utils.extend({}, options, {paged: true});
var arr = [];
exports.defaults = function(appOptions) {
const defaults = { apiurl: 'https://api.github.com', method: 'get', params: [] };
if (typeof opts.url !== 'string') {
cb(new TypeError('expected options.url to be a string'));
return;
}
return function(method, uri, methodOptions) {
const options = Object.assign({}, defaults, appOptions, methodOptions, { uri, method });
const context = { orig: Object.assign({}, options), options: lowercaseKeys(options) };
context.options.url = interpolate(uri, context);
context.options.headers = createHeaders(context.options);
function request(first) {
if (first) opts.url = setPageLimit(opts.url);
let opts = context.options;
const body = omit(context.orig, Object.keys(opts));
const json = opts.json;
const text = opts.body;
utils.request(opts, function(err, data, stream) {
if (err) {
cb(err);
return;
}
if (!opts.mode && /\/markdown(?!\/raw)/.test(opts.url)) {
opts.mode = 'gfm';
}
try {
if (data && Array.isArray(data)) {
arr.push.apply(arr, data);
}
var page = utils.parseLink(stream.headers.link);
if (page && page.next) {
opts.url = page.next.url;
request();
} else {
cb(null, arr, stream);
}
} catch (err) {
cb(err);
const bodyKeys = Object.keys(body);
if (bodyKeys.length > 0) {
opts = omit(opts, bodyKeys);
opts.headers['content-length'] = JSON.stringify(body).length;
if (typeof opts.headers['content-type'] !== 'string') {
opts.headers['content-type'] = 'application/json';
}
});
}
request(true);
};
} else if (lowercase(opts.method) === 'put') {
opts.headers['content-length'] = 0;
}
/**
* Default settings to use for GitHub API requests.
*
* @param {Object} `options`
* @return {Object}
*/
if (typeof json === 'boolean') {
opts.json = json;
}
utils.defaults = function(options) {
return function(method, url, data) {
var opts = utils.extend({method: 'get'}, options);
opts.apiurl = opts.apiurl || 'https://api.github.com';
var config = lowercaseKeys(opts);
opts = utils.merge({}, config, data);
opts = interpolate(url, opts);
opts = createURL(opts);
opts = lowercaseKeys(opts);
opts = createAuth(opts);
opts = cleanup(opts);
opts.method = method.toLowerCase();
opts = normalizeOpts(opts, config);
if (text) {
opts.body = opts.json !== true ? JSON.stringify(text) : text;
}
var defaults = {
'accept': 'application/json',
'user-agent': 'https://github.com/jonschlinkert/github-base'
};
opts.headers = utils.extend({}, defaults, lowercaseKeys(opts.headers));
opts = sanitize(opts, opts.params);
return opts;

@@ -124,124 +106,117 @@ };

/**
* Replace params with actual values.
* Create auth string - token, Bearer or Basic Auth
*/
function interpolate(path, options) {
var opts = utils.extend({}, options, {params: []});
opts.url = path.replace(/:([\w_]+)/g, function(m, prop) {
opts.params.push(prop);
return opts[prop] || prop;
});
return opts;
}
function createHeaders(options) {
const opts = Object.assign({}, options);
const headers = Object.assign({}, defaultHeaders, opts.headers);
/**
* Create url to request and prevent cache
*/
function createURL(opts) {
opts.url += setPrefix(opts.url);
opts.url += (new Date()).getTime();
opts.url = opts.apiurl + opts.url;
return opts;
}
/**
* Lowercase the keys in the given object.
*/
function lowercaseKeys(obj) {
var res = {};
for (var key in obj) res[key.toLowerCase()] = obj[key];
return res;
}
/**
* Create auth string - token, Bearer or Basic Auth
*/
function createAuth(options) {
var opts = utils.merge({headers: {}}, options);
if (!opts.bearer && !opts.token && !opts.username && !opts.password) {
return opts;
return headers;
}
if (opts.token) {
opts.headers['authorization'] = 'token ' + opts.token;
return opts;
headers['authorization'] = 'token ' + opts.token;
return headers;
}
if (opts.bearer) {
opts.headers['authorization'] = 'Bearer ' + opts.bearer;
return opts;
headers['authorization'] = 'Bearer ' + opts.bearer;
return headers;
}
var creds = opts.username + ':' + opts.password;
opts.headers['authorization'] = 'Basic ' + toBase64(creds);
return opts;
const creds = opts.username + ':' + opts.password;
headers['authorization'] = 'Basic ' + toBase64(creds);
return headers;
}
/**
* Cleanup request options object
* Create request URL by replacing params with actual values.
*/
function cleanup(options) {
var opts = utils.extend({}, options);
var keys = ['apiurl', 'token', 'username', 'password', 'placeholders'];
if (Array.isArray(opts.params) && opts.params.length) {
keys = keys.concat(opts.params);
function interpolate(str, context) {
const opts = { ...context.options };
let val = opts.apiurl + str.replace(/:([\w_]+)/g, (m, key) => {
opts.params = union(opts.params, key);
let val = get(opts, key);
if (val !== void 0) {
return val;
}
return key;
});
if (opts.method.toLowerCase() === 'get' && opts.paged !== false) {
const obj = url.parse(val);
const query = obj.query ? qs.parse(obj.query) : {};
const noquery = omit(obj, ['query', 'search']);
noquery.query = noquery.search = qs.stringify(Object.assign({ per_page: 100 }, opts.query, query));
val = url.format(noquery);
}
return utils.omit(opts, keys);
val += /\?/.test(val) ? '&' : '?';
val += (new Date()).getTime();
return val;
}
/**
* Normalize request options object,
* the request body and few body-related headers
*/
function result(res, data, opts, options) {
if (res.statusCode >= 400) {
const err = new Error(res.body.message);
Reflect.defineProperty(err, 'res', { value: res, enumerable: false });
return Promise.reject(err);
}
function normalizeOpts(options, config) {
var opts = utils.extend({}, options);
var json = opts.json;
var keys = Object.keys(config).concat(['headers', 'method', 'url', 'params']);
var body = utils.omit(opts, keys);
var text;
if (!res.url) res.url = opts.url;
if (res.op) res.id = options.id;
if (/markdown\/raw/.test(opts.url)) {
text = opts.body;
if (/\/markdown\/raw/.test(res.url) && opts.headers['content-type'] === 'text/plain') {
try {
const parsed = JSON.parse(res.body.trim().replace(/^<p>|<\/p>$/g, ''));
res.body = `<p>${parsed.body}</p>\n`;
} catch (err) { /* do nothing */ }
}
var bodyKeys = Object.keys(body);
if (bodyKeys.length) {
opts = utils.omit(opts, bodyKeys);
var bodyString = JSON.stringify(body);
opts.body = body;
opts.headers['content-length'] = bodyString.length;
return Object.assign({}, data, res);
}
if (!isString(opts.headers['content-type'])) {
opts.headers['content-type'] = 'application/json';
}
} else if (String(opts.method).toLowerCase() === 'put') {
opts.headers['content-length'] = 0;
}
/**
* Cleanup request options object
*/
if (text) {
opts.body = text;
} else if (opts.json !== true) {
opts.body = JSON.stringify(opts.body);
}
function sanitize(options, blacklist) {
const opts = Object.assign({}, options);
const defaults = ['apiurl', 'token', 'username', 'password', 'placeholders', 'bearer'];
const keys = union([], defaults, blacklist);
return omit(opts, keys);
}
opts.json = json;
return opts;
function lowercaseKeys(obj) {
const acc = {};
for (const key of Object.keys(obj)) acc[lowercase(key)] = obj[key];
return acc;
}
function isString(str) {
return str && typeof str === 'string';
function lowercase(str) {
return typeof str === 'string' ? str.toLowerCase() : '';
}
function setPageLimit(str) {
var url = str.replace(/[?&]per_page=\d+/, '');
return url + setPrefix(url) + 'per_page=100';
function omit(obj, keys) {
keys = [].concat(keys || []);
let res = {};
for (const key of Object.keys(obj)) {
if (!keys.includes(key)) {
res[key] = obj[key];
}
}
return res;
}
function setPrefix(url) {
return /\?/.test(url) ? '&' : '?';
function union(...args) {
const arr = new Set();
for (const arg of args) {
for (const ele of [].concat(arg)) {
if (ele) arr.add(ele);
}
}
return [...arr];
}

@@ -254,3 +229,3 @@

function toBase64(str) {
return new Buffer(str).toString('base64');
return Buffer.from(str).toString('base64');
}
{
"name": "github-base",
"description": "JavaScript wrapper that greatly simplifies working with GitHub's API.",
"version": "0.5.4",
"description": "Low-level methods for working with the GitHub API in node.js/JavaScript.",
"version": "1.0.0",
"homepage": "https://github.com/jonschlinkert/github-base",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"contributors": [
"Brian Woodward <brian.woodward@gmail.com> (https://twitter.com/doowb)",
"Charlike Mike Reagent (https://i.am.charlike.online)",
"Jon Schlinkert <jon.schlinkert@sellside.com> (http://twitter.com/jonschlinkert)"
"Brian Woodward (https://twitter.com/doowb)",
"Jon Schlinkert (http://twitter.com/jonschlinkert)",
"Olsten Larck (https://i.am.charlike.online)"
],

@@ -23,3 +23,3 @@ "repository": "jonschlinkert/github-base",

"engines": {
"node": ">=0.10.0"
"node": ">=8"
},

@@ -30,17 +30,15 @@ "scripts": {

"dependencies": {
"define-property": "^0.2.5",
"extend-shallow": "^2.0.1",
"is-buffer": "^1.1.5",
"mixin-deep": "^1.2.0",
"object.omit": "^2.0.1",
"parse-link-header": "^0.4.1",
"simple-get": "^2.5.1",
"static-extend": "^0.1.2",
"use": "^3.0.0"
"get-value": "^3.0.1",
"needle": "^2.2.2",
"paged-request": "^1.0.2",
"parse-link-header": "^1.0.1",
"qs": "^6.5.1",
"use": "^3.1.0"
},
"devDependencies": {
"data-store": "^0.16.1",
"gulp-format-md": "^0.1.12",
"mocha": "^3.2.0",
"yargs-parser": "^5.0.0"
"minimist": "^1.2.0",
"data-store": "^1.0.0",
"mocha": "^3.5.3",
"kind-of": "^6.0.2",
"gulp-format-md": "^1.0.0"
},

@@ -63,2 +61,8 @@ "keywords": [

"layout": "default",
"toc": {
"render": true,
"method": "preWrite",
"collapsible": true,
"maxdepth": 4
},
"tasks": [

@@ -72,4 +76,5 @@ "readme"

"list": [
"ask-for-github-auth",
"gists",
"repos",
"topics",
"github-contributors"

@@ -79,8 +84,7 @@ ]

"reflinks": [
"simple-get",
"static-extend",
"verb",
"verb-generate-readme"
"needle",
"qs",
"use"
]
}
}

@@ -1,5 +0,40 @@

# github-base [![NPM version](https://img.shields.io/npm/v/github-base.svg?style=flat)](https://www.npmjs.com/package/github-base) [![NPM monthly downloads](https://img.shields.io/npm/dm/github-base.svg?style=flat)](https://npmjs.org/package/github-base) [![NPM total downloads](https://img.shields.io/npm/dt/github-base.svg?style=flat)](https://npmjs.org/package/github-base) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/github-base.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/github-base)
# github-base [![NPM version](https://img.shields.io/npm/v/github-base.svg?style=flat)](https://www.npmjs.com/package/github-base) [![NPM monthly downloads](https://img.shields.io/npm/dm/github-base.svg?style=flat)](https://npmjs.org/package/github-base) [![NPM total downloads](https://img.shields.io/npm/dt/github-base.svg?style=flat)](https://npmjs.org/package/github-base) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/github-base.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/github-base) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/github-base.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/github-base)
> JavaScript wrapper that greatly simplifies working with GitHub's API.
> Low-level methods for working with the GitHub API in node.js/JavaScript.
Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
## Table of Contents
<details>
<summary><strong>Details</strong></summary>
- [Install](#install)
- [Heads up!](#heads-up)
- [Why github-base, instead of...?](#why-github-base-instead-of)
- [Usage](#usage)
- [API](#api)
* [GitHub](#github)
* [.request](#request)
* [.get](#get)
* [.delete](#delete)
* [.patch](#patch)
* [.post](#post)
* [.put](#put)
* [.paged](#paged)
* [.use](#use)
- [Authentication](#authentication)
- [Paths and placeholders](#paths-and-placeholders)
- [Options](#options)
* [options.query](#optionsquery)
- [About](#about)
* [Related projects](#related-projects)
* [Contributors](#contributors)
* [Author](#author)
* [License](#license)
_(TOC generated by [verb](https://github.com/verbose/verb) using [markdown-toc](https://github.com/jonschlinkert/markdown-toc))_
</details>
## Install

@@ -13,44 +48,47 @@

**Heads up!**
## Heads up!
This lib was completely refactored in `v0.2.0`. Please see the [API documentation](#API) for more details.
As of v1.0, the API is 100% promise based, callbacks are no longer supported. Please see the [API documentation](#API) and [release history](changelog.md) for more details.
**About**
## Why github-base, instead of...?
This library provides the necessary methods for creating your own GitHub API library or more specific functionality built on top of these methods.
Every other GitHub API library we found either had a [huge dependency tree](https://github.com/sindresorhus/gh-got), tries to be [everything to everyone](https://github.com/michael/github/blob/master/package.json#L45-L56), was [too bloated with boilerplace code](https://github.com/mikedeboer/node-github/tree/master/templates), was too opinionated, or was not maintained.
* [.request](#request): the base handler all of the GitHub API VERBS: `GET`, `PUT`, `POST`, `DELETE`, `PATCH`
* [.get](#get): proxy for `request('GET', path, data, cb)`
* [.paged](#paged): makes repeat `.get()` requests until the page of data has been retrieved.
* [.del](#del): proxy for `request('DEL', path, data, cb)`
* [.patch](#patch): proxy for `request('PATCH', path, data, cb)`
* [.post](#post): proxy for `request('POST', path, data, cb)`
* [.put](#put): proxy for `request('PUT', path, data, cb)`
We created github-base to provide low-level support for a handful of HTTP verbs for creating higher-level libraries:
* [.request](#request): the base handler all of the GitHub HTTP verbs: `GET`, `PUT`, `POST`, `DELETE`, `PATCH`
* [.get](#get): proxy for `.request('GET', path, options, cb)`
* [.delete](#delete): proxy for `.request('DELETE', path, options, cb)`
* [.patch](#patch): proxy for `.request('PATCH', path, options, cb)`
* [.post](#post): proxy for `.request('POST', path, options, cb)`
* [.put](#put): proxy for `.request('PUT', path, options, cb)`
* [.paged](#paged): recursively makes `GET` requests until all pages have been retrieved.
Jump to the [API section](#API) for more details.
## Usage
Add github-base to your node.js/JavaScript project with the following line of code:
```js
var GitHub = require('github-base');
var github = new GitHub({
username: YOUR_USERNAME,
password: YOUR_PASSWORD,
});
const GitHub = require('github-base');
```
// or
var github = new GitHub({
token: YOUR_TOKEN
});
**Example usage**
// or
var github = new GitHub({
bearer: YOUR_JWT
});
```
Recursively `GET` all pages of gists for a user:
## Why another "GitHub API" lib?
```js
const github = new GitHub({ /* options */ });
const owner = 'jonschlinkert';
Every other GitHub API library I found either had a [huge dependency tree](https://github.com/sindresorhus/gh-got), tries to be [everything to everyone](https://github.com/michael/github/blob/master/package.json#L45-L56), was [too bloated with boilerplace code](https://github.com/mikedeboer/node-github/tree/master/templates), was too opinionated or not maintained.
github.paged(`/users/${owner}/gists`)
.then(res => console.log(res))
.catch(console.error);
```
## API
_(All request methods take a callback, or return a promise if a callback isn't passed as the last argument)_.
### [GitHub](index.js#L18)

@@ -67,22 +105,15 @@

```js
var GitHub = require('github-base');
var github = new GitHub(options);
const GitHub = require('github-base');
const github = new GitHub([options]);
```
### [.request](index.js#L59)
### [.request](index.js#L42)
Uses [simple-get](https://github.com/feross/simple-get) to make a single request to the GitHub API, based on the provided settings. Supports any of the GitHub API VERBs:
Uses [needle](https://github.com/tomas/needle) to make a request to the GitHub API. Supports the following verbs: `GET`, `PUT`, `POST`, `PATCH`, and `DELETE`. Takes a callback or returns a promise.
* `GET`
* `PUT`
* `POST`
* `DELETE`
* `PATCH`
**Params**
* `method` **{String}**: The http VERB to use
* `url` **{String}**: GitHub API URL to use.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -92,17 +123,17 @@ **Example**

```js
//example..request
github.request('GET', '/user/orgs', function (err, res) {
//=> array of orgs
});
// list all orgs for the authenticated user
const auth = require('./local-private-auth-info');
const github = new GitHub(auth);
github.request('GET', '/user/orgs')
.then(res => console.log(res.body));
```
### [.get](index.js#L91)
### [.get](index.js#L64)
Makes a single `GET` request to the GitHub API based on the provided settings.
Make a `GET` request to the GitHub API.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -112,21 +143,19 @@ **Example**

```js
// get orgs for the authenticated user
github.get('/user/orgs', function (err, res) {
//=> array of orgs
});
// get a list of orgs for the authenticated user
github.get('/user/orgs')
.then(res => console.log(res.body));
// get gists for the authenticated user
github.get('/gists', function (err, res) {
//=> array of gists
});
github.get('/gists')
.then(res => console.log(res.body));
```
### [.paged](index.js#L113)
### [.delete](index.js#L84)
Performs a request using [simple-get](https://github.com/feross/simple-get), and then if necessary requests additional paged content based on the response. Data from all pages are concatenated together and buffered until the last page of data has been retrieved.
Make a `DELETE` request to the GitHub API.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -136,18 +165,17 @@ **Example**

```js
// get all repos for the authenticated user
var url = '/user/repos?type=all&per_page=1000&sort=updated';
github.paged(url, function(err, res) {
console.log(res);
});
// un-follow someone
github.delete('/user/following/:some_username', { some_username: 'whatever' })
.then(res => {
console.log('RESPONSE:', res);
});
```
### [.del](index.js#L138)
### [.patch](index.js#L106)
Makes a single `DELETE` request to the GitHub API based on the provided settings.
Make a `PATCH` request to the GitHub API.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -157,17 +185,19 @@ **Example**

```js
// un-follow someone
github.del('/user/following/someoneelse', function(err, res) {
console.log(res);
});
// update a gist
const fs = require('fs');
const options = { files: { 'readme.md': { content: fs.readFileSync('README.md', 'utf8') } } };
github.patch('/gists/bd139161a425896f35f8', options)
.then(res => {
console.log('RESPONSE:', res);
});
```
### [.patch](index.js#L161)
### [.post](index.js#L126)
Makes a single `PATCH` request to the GitHub API based on the provided settings.
Make a `POST` request to the GitHub API.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -177,19 +207,17 @@ **Example**

```js
// update a gist
var fs = require('fs');
var opts = {files: {'readme.md': { content: '# My Readme...' }}};
github.patch('/gists/bd139161a425896f35f8', opts, function(err, res) {
console.log(err, res);
});
// create a new repository
github.post('/user/repos', { name: 'new-repo-name' })
.then(res => {
console.log('RESPONSE:', res);
});
```
### [.post](index.js#L183)
### [.put](index.js#L146)
Makes a single `POST` request to the GitHub API based on the provided settings.
Make a `PUT` request to the GitHub API.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -199,18 +227,17 @@ **Example**

```js
// create a new repo
var opts = { name: 'new-repo-name' };
github.post('/user/repos', opts, function(err, res) {
console.log(res);
});
// follow someone
github.put('/user/following/jonschlinkert')
.then(res => {
console.log('RESPONSE:', res);
});
```
### [.put](index.js#L204)
### [.paged](index.js#L165)
Makes a single `PUT` request to the GitHub API based on the provided settings.
Recursively make GET requests until all pages of records are returned.
**Params**
* `path` **{String}**: path to append to the GitHub API URL.
* `options` **{Options}**: Request options.
* `cb` **{Function}**
* `path` **{String}**: The path to append to the base GitHub API URL.
* `options` **{Options}**: Request [options](#options).

@@ -220,48 +247,128 @@ **Example**

```js
// follow someone
github.put('/user/following/jonschlinkert', function(err, res) {
console.log(res);
// get all repos for the authenticated user
github.paged('/user/repos?type=all&per_page=1000&sort=updated')
.then(res => console.log(res.pages))
.catch(console.error)
```
### .use
Register plugins with [use](https://github.com/jonschlinkert/use).
```js
const github = new GitHub();
github.use(function() {
// do stuff with the github-base instance
});
```
### [#extend](index.js#L226)
## Authentication
Static method for inheriting the prototype and static methods of the `Base` class. This method greatly simplifies the process of creating inheritance-based applications. See [static-extend](https://github.com/jonschlinkert/static-extend) for more details.
There are a few ways to authenticate, all of them require info to be passed on the [options](#options).
**Params**
```js
const github = new GitHub({
username: YOUR_USERNAME,
password: YOUR_PASSWORD,
});
* `Ctor` **{Function}**: constructor to extend
// or
const github = new GitHub({
token: YOUR_TOKEN
});
**Example**
// or
const github = new GitHub({
bearer: YOUR_JSON_WEB_TOKEN
});
```
## Paths and placeholders
**Deprecated**: Since es2015 templates make this feature less useful, we plan to remove it in a future release.
Paths are similar to router paths, where placeholders in the given string are replaced with values from the options. For instance, the path in the following example:
```js
var GitHub = require('github-base');
function MyApp() {
GitHub.call(this);
}
GitHub.extend(MyApp);
const github = new GitHub();
const options = { user: 'jonschlinkert', repo: 'github-base', subscribed: true };
github.put('/repos/:user/:repo/subscription', options);
```
## About
Expands to:
### Related projects
```js
'/repos/jonschlinkert/github-base/subscription'
```
* [ask-for-github-auth](https://www.npmjs.com/package/ask-for-github-auth): Prompt a user for their github authentication credentials and save the results. | [homepage](https://github.com/doowb/ask-for-github-auth "Prompt a user for their github authentication credentials and save the results.")
* [gists](https://www.npmjs.com/package/gists): Methods for working with the GitHub Gist API. Node.js/JavaScript | [homepage](https://github.com/jonschlinkert/gists "Methods for working with the GitHub Gist API. Node.js/JavaScript")
* [github-contributors](https://www.npmjs.com/package/github-contributors): Generate a markdown or JSON list of contributors for a project using the GitHub API. | [homepage](https://github.com/jonschlinkert/github-contributors "Generate a markdown or JSON list of contributors for a project using the GitHub API.")
Placeholder names are also arbitrary, you can make them whatever you want as long as all placeholder names can be resolved using values defined on the options.
### Contributing
## Options
Options may be passed to the constructor when instantiating, and/or set on the instance directly, and/or passed to any of the methods.
**Examples**
```js
// pass to constructor
const github = new GitHub({ user: 'doowb' });
// and/or directly set on instance options
github.options.user = 'doowb';
// and/or pass to a method
github.get('/users/:user/gists', { user: 'doowb' })
```
### options.query
**Type**: `object`
**Default**: `{ per_page: 100 }` for [get](#get) and [paged](#paged) requests, `undefined` for all other requests.
Pass an object to stringify and append to the URL using the `.stringify` method from [qs](https://github.com/ljharb/qs).
**Examples**
```js
github.paged('/users/:user/gists', { user: 'doowb', query: { per_page: 30 } })
.then(res => {
console.log(res.pages);
});
```
You can also manually append the query string:
```js
github.paged('/users/:user/gists?per_page=30', { user: 'doowb' })
.then(res => {
console.log(res.pages);
});
```
## About
<details>
<summary><strong>Contributing</strong></summary>
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### Contributors
</details>
| **Commits** | **Contributor** |
| --- | --- |
| 31 | [jonschlinkert](https://github.com/jonschlinkert) |
| 7 | [tunnckoCore](https://github.com/tunnckoCore) |
| 6 | [doowb](https://github.com/doowb) |
<details>
<summary><strong>Running Tests</strong></summary>
### Building docs
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
```sh
$ npm install && npm test
```
</details>
<details>
<summary><strong>Building docs</strong></summary>
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_

@@ -275,10 +382,21 @@

### Running tests
</details>
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
### Related projects
```sh
$ npm install && npm test
```
You might also be interested in these projects:
* [gists](https://www.npmjs.com/package/gists): Methods for working with the GitHub Gist API. Node.js/JavaScript | [homepage](https://github.com/jonschlinkert/gists "Methods for working with the GitHub Gist API. Node.js/JavaScript")
* [github-contributors](https://www.npmjs.com/package/github-contributors): Generate a markdown or JSON list of contributors for a project using the GitHub API. | [homepage](https://github.com/jonschlinkert/github-contributors "Generate a markdown or JSON list of contributors for a project using the GitHub API.")
* [repos](https://www.npmjs.com/package/repos): List all repositories for one or more users or orgs. | [homepage](https://github.com/jonschlinkert/repos "List all repositories for one or more users or orgs.")
* [topics](https://www.npmjs.com/package/topics): Get and update GitHub repository topics. | [homepage](https://github.com/jonschlinkert/topics "Get and update GitHub repository topics.")
### Contributors
| **Commits** | **Contributor** |
| --- | --- |
| 40 | [jonschlinkert](https://github.com/jonschlinkert) |
| 10 | [doowb](https://github.com/doowb) |
| 7 | [olstenlarck](https://github.com/olstenlarck) |
### Author

@@ -288,8 +406,9 @@

* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
* [GitHub Profile](https://github.com/jonschlinkert)
* [Twitter Profile](https://twitter.com/jonschlinkert)
* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
### License
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).

@@ -299,2 +418,2 @@

_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.3, on April 06, 2017._
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on August 14, 2018._

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc