ghusers 0.2.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'github-actions'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'weekly'
7
+ commit-message:
8
+ prefix: 'chore'
9
+ include: 'scope'
10
+ cooldown:
11
+ default-days: 5
12
+ - package-ecosystem: 'npm'
13
+ directory: '/'
14
+ schedule:
15
+ interval: 'weekly'
16
+ commit-message:
17
+ prefix: 'chore'
18
+ include: 'scope'
19
+ cooldown:
20
+ default-days: 5
@@ -0,0 +1,56 @@
1
+ name: Test & Maybe Release
2
+ on: [push, pull_request]
3
+
4
+ jobs:
5
+ test:
6
+ strategy:
7
+ fail-fast: false
8
+ matrix:
9
+ node: [lts/*, current]
10
+ os: [macos-latest, ubuntu-latest, windows-latest]
11
+ runs-on: ${{ matrix.os }}
12
+ steps:
13
+ - name: Checkout Repository
14
+ uses: actions/checkout@v6
15
+ - name: Use Node.js ${{ matrix.node }}
16
+ uses: actions/setup-node@v6
17
+ with:
18
+ node-version: ${{ matrix.node }}
19
+ - name: Install Dependencies
20
+ run: npm install --no-progress
21
+ - name: Check build is up to date
22
+ run: |
23
+ npm run build
24
+ git diff --exit-code || (echo "::error::Build artifacts not committed. Run 'npm run build' and commit the changes." && exit 1)
25
+ - name: Run tests
26
+ run: npm test
27
+
28
+ release:
29
+ name: Release
30
+ needs: test
31
+ runs-on: ubuntu-latest
32
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
33
+ permissions:
34
+ contents: write
35
+ issues: write
36
+ pull-requests: write
37
+ id-token: write
38
+ steps:
39
+ - name: Checkout
40
+ uses: actions/checkout@v6
41
+ with:
42
+ fetch-depth: 0
43
+ - name: Setup Node.js
44
+ uses: actions/setup-node@v6
45
+ with:
46
+ node-version: lts/*
47
+ registry-url: 'https://registry.npmjs.org'
48
+ - name: Install dependencies
49
+ run: npm install --no-progress --no-package-lock --no-save
50
+ - name: Build
51
+ run: npm run build
52
+ - name: Release
53
+ env:
54
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55
+ NPM_CONFIG_PROVENANCE: true
56
+ run: npx semantic-release
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ ## [1.0.0](https://github.com/rvagg/ghusers/compare/v0.2.3...v1.0.0) (2026-01-27)
2
+
3
+ ### ⚠ BREAKING CHANGES
4
+
5
+ * modernise, ESM, promises, update deps, GHA, auto-release (#2)
6
+
7
+ ### Bug Fixes
8
+
9
+ * add release config ([5634369](https://github.com/rvagg/ghusers/commit/5634369e698b8991f075d7440cbf6c48d0386fab))
10
+
11
+ ### Trivial Changes
12
+
13
+ * modernise, ESM, promises, update deps, GHA, auto-release ([#2](https://github.com/rvagg/ghusers/issues/2)) ([26f55f1](https://github.com/rvagg/ghusers/commit/26f55f196cca3b651b6abdbcc030c3dd64f5e53c))
package/README.md CHANGED
@@ -1,43 +1,60 @@
1
1
  # ghusers
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/rvagg/ghusers.png)](http://travis-ci.org/rvagg/ghusers)
3
+ **A Node.js library to interact with the GitHub users API**
4
4
 
5
- **A node library to interact with the GitHub users API**
5
+ [![NPM](https://nodei.co/npm/ghusers.svg?style=flat&data=n,v&color=blue)](https://nodei.co/npm/ghusers/)
6
6
 
7
- [![NPM](https://nodei.co/npm/ghusers.png?mini=true)](https://nodei.co/npm/ghusers/)
7
+ ## Requirements
8
+
9
+ - Node.js >= 20
8
10
 
9
11
  ## Example usage
10
12
 
11
13
  ```js
12
- const ghusers = require('ghusers')
13
- , authOptions = { user: 'rvagg', token: '24d5dee258c64aef38a66c0c5eca459c379901c2' }
14
+ import * as ghusers from 'ghusers'
15
+
16
+ const auth = { token: 'your-github-token' }
14
17
 
15
18
  // get user by login/username
16
- ghusers.get(authOptions, 'substack', function (err, user) {
17
- // object containing full details of @substack
18
- console.log(user)
19
- })
19
+ const user = await ghusers.get(auth, 'substack')
20
+ console.log(user)
20
21
  ```
21
22
 
22
-
23
- The auth data is compatible with [ghauth](https://github.com/rvagg/ghauth) so you can just connect them together to make a simple command-line application:
23
+ The auth data is compatible with [ghauth](https://github.com/rvagg/ghauth) so you can connect them together:
24
24
 
25
25
  ```js
26
- const ghauth = require('ghauth')
27
- , ghusers = require('ghusers')
28
- , authOptions = {
29
- configName : 'team-lister'
30
- , scopes : [ 'user' ]
31
- }
32
-
33
- ghauth(authOptions, function (err, authData) {
34
- ghusers.get(authData, 'rvagg', function (err, user) {
35
- console.log(user)
36
- })
26
+ import ghauth from 'ghauth'
27
+ import * as ghusers from 'ghusers'
28
+
29
+ const auth = await ghauth({
30
+ configName: 'user-lookup',
31
+ scopes: ['user']
37
32
  })
33
+
34
+ const user = await ghusers.get(auth, 'rvagg')
35
+ console.log(user)
38
36
  ```
39
37
 
38
+ ## API
39
+
40
+ All methods return Promises.
41
+
42
+ ### ghusers.get(auth, user, options)
43
+
44
+ Get full user data for a given login/username.
45
+
46
+ ## Authentication
47
+
48
+ See [ghauth](https://github.com/rvagg/ghauth) for an easy way to obtain and cache GitHub authentication tokens. The `auth` object returned by ghauth is directly compatible with all ghusers methods.
49
+
50
+ ## See also
51
+
52
+ * [ghissues](https://github.com/rvagg/ghissues) - interact with the GitHub issues API
53
+ * [ghpulls](https://github.com/rvagg/ghpulls) - interact with the GitHub pull requests API
54
+ * [ghteams](https://github.com/rvagg/ghteams) - interact with the GitHub teams API
55
+ * [ghrepos](https://github.com/rvagg/ghrepos) - interact with the GitHub repos API
56
+ * [ghauth](https://github.com/rvagg/ghauth) - GitHub authentication
40
57
 
41
58
  ## License
42
59
 
43
- **ghusers** is Copyright (c) 2014 Rod Vagg [@rvagg](https://github.com/rvagg) and licensed under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
60
+ **ghusers** is Copyright (c) 2014-2025 Rod Vagg [@rvagg](https://github.com/rvagg) and licensed under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.
package/ghusers.js CHANGED
@@ -1,43 +1,10 @@
1
- const jsonist = require('jsonist')
2
- , qs = require('querystring')
3
- , xtend = require('xtend')
1
+ import { ghget } from 'ghutils'
4
2
 
3
+ const defaultApiUrl = 'https://api.github.com'
5
4
 
6
- function makeOptions (auth, options) {
7
- return xtend({
8
- headers : { 'User-Agent' : 'Magic Node.js application that does magic things' }
9
- , auth : auth.user + ':' + auth.token
10
- }, options)
11
- }
12
-
13
-
14
- function handler (callback) {
15
- return function responseHandler (err, data) {
16
- if (err)
17
- return callback(err)
18
-
19
- if (data.error || data.message)
20
- return callback(new Error('Error from GitHub: ' + (data.error || data.message)))
21
-
22
- callback(null, data)
23
- }
24
- }
25
-
26
-
27
- function ghget (auth, url, options, callback) {
28
- options = makeOptions(auth, options)
29
-
30
- jsonist.get(url, options, handler(callback))
31
- }
32
-
33
-
34
- module.exports.get = function get (auth, user, options, callback) {
35
- if (typeof options == 'function') {
36
- callback = options
37
- options = {}
38
- }
39
-
40
- var url = 'https://api.github.com/users/' + user
41
-
42
- ghget(auth, url, options, callback)
5
+ export async function get (auth, user, options = {}) {
6
+ const apiUrl = options._apiUrl || defaultApiUrl
7
+ const url = `${apiUrl}/users/${user}`
8
+ const { data } = await ghget(auth, url, options)
9
+ return data
43
10
  }
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "ghusers",
3
- "version": "0.2.2",
3
+ "version": "1.0.0",
4
4
  "description": "Interact with the GitHub users API",
5
- "main": "ghusers.js",
5
+ "type": "module",
6
+ "exports": "./ghusers.js",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
6
10
  "scripts": {
7
- "test": "node test.js"
11
+ "lint": "standard",
12
+ "build": "true",
13
+ "test:unit": "node --test test.js",
14
+ "test": "npm run lint && npm run test:unit"
8
15
  },
9
16
  "repository": {
10
17
  "type": "git",
@@ -21,13 +28,98 @@
21
28
  },
22
29
  "homepage": "https://github.com/rvagg/ghusers",
23
30
  "dependencies": {
24
- "jsonist": "~1.0.1",
25
- "xtend": "~4.0.0"
31
+ "ghutils": "^5.0.2"
26
32
  },
27
33
  "devDependencies": {
28
- "bl": "~0.9.4",
29
- "hyperquest": "~1.2.0",
30
- "require-subvert": "~0.1.0",
31
- "tape": "~4.0.0"
34
+ "@semantic-release/changelog": "^6.0.3",
35
+ "@semantic-release/commit-analyzer": "^13.0.1",
36
+ "@semantic-release/git": "^10.0.1",
37
+ "@semantic-release/github": "^12.0.2",
38
+ "@semantic-release/npm": "^13.1.3",
39
+ "@semantic-release/release-notes-generator": "^14.1.0",
40
+ "conventional-changelog-conventionalcommits": "^9.1.0",
41
+ "semantic-release": "^25.0.2",
42
+ "standard": "^17.1.2"
43
+ },
44
+ "release": {
45
+ "branches": [
46
+ "master"
47
+ ],
48
+ "plugins": [
49
+ [
50
+ "@semantic-release/commit-analyzer",
51
+ {
52
+ "preset": "conventionalcommits",
53
+ "releaseRules": [
54
+ {
55
+ "breaking": true,
56
+ "release": "major"
57
+ },
58
+ {
59
+ "revert": true,
60
+ "release": "patch"
61
+ },
62
+ {
63
+ "type": "feat",
64
+ "release": "minor"
65
+ },
66
+ {
67
+ "type": "fix",
68
+ "release": "patch"
69
+ },
70
+ {
71
+ "type": "chore",
72
+ "release": "patch"
73
+ },
74
+ {
75
+ "type": "docs",
76
+ "release": "patch"
77
+ },
78
+ {
79
+ "type": "test",
80
+ "release": "patch"
81
+ },
82
+ {
83
+ "scope": "no-release",
84
+ "release": false
85
+ }
86
+ ]
87
+ }
88
+ ],
89
+ [
90
+ "@semantic-release/release-notes-generator",
91
+ {
92
+ "preset": "conventionalcommits",
93
+ "presetConfig": {
94
+ "types": [
95
+ {
96
+ "type": "feat",
97
+ "section": "Features"
98
+ },
99
+ {
100
+ "type": "fix",
101
+ "section": "Bug Fixes"
102
+ },
103
+ {
104
+ "type": "chore",
105
+ "section": "Trivial Changes"
106
+ },
107
+ {
108
+ "type": "docs",
109
+ "section": "Trivial Changes"
110
+ },
111
+ {
112
+ "type": "test",
113
+ "section": "Tests"
114
+ }
115
+ ]
116
+ }
117
+ }
118
+ ],
119
+ "@semantic-release/changelog",
120
+ "@semantic-release/npm",
121
+ "@semantic-release/github",
122
+ "@semantic-release/git"
123
+ ]
32
124
  }
33
125
  }
package/test.js CHANGED
@@ -1,105 +1,35 @@
1
- const http = require('http')
2
- , test = require('tape')
3
- , requireSubvert = require('require-subvert')(__dirname)
4
- , _hyperquest = require('hyperquest')
5
- , xtend = require('xtend')
6
- , EE = require('events').EventEmitter
7
- , bl = require('bl')
8
-
9
-
10
- requireSubvert.subvert('hyperquest', hyperquest)
11
-
12
- var ghusers = require('./')
13
- , hyperget
14
-
15
- function hyperquest () {
16
- return hyperget.apply(this, arguments)
17
- }
18
-
19
-
20
- function makeServer (data) {
21
- var ee = new EE()
22
- , i = 0
23
- , server = http.createServer(function (req, res) {
24
- ee.emit('request', req)
25
-
26
- var _data = Array.isArray(data) ? data[i++] : data
27
- res.end(JSON.stringify(_data))
28
-
29
- if (!Array.isArray(data) || i == data.length)
30
- server.close()
31
- })
32
- .listen(0, function (err) {
33
- if (err)
34
- return ee.emit('error', err)
35
-
36
- hyperget = function (url, opts) {
37
- ee.emit('get', url, opts)
38
- return _hyperquest('http://localhost:' + server.address().port, opts)
39
- }
40
-
41
- ee.emit('ready')
42
- })
43
- .on('close', ee.emit.bind(ee, 'close'))
44
-
45
- return ee
46
- }
47
-
48
-
49
- function toAuth (auth) {
50
- return 'Basic ' + (new Buffer(auth.user + ':' + auth.token).toString('base64'))
51
- }
52
-
53
-
54
- function verifyRequest (t, auth) {
55
- return function (req) {
56
- t.ok(true, 'got request')
57
- t.equal(req.headers['authorization'], toAuth(auth), 'got auth header')
58
- }
59
- }
60
-
61
-
62
- function verifyUrl (t, urls) {
63
- var i = 0
64
- return function (_url) {
65
- if (i == urls.length)
66
- return t.fail('too many urls/requests')
67
- t.equal(_url, urls[i++], 'correct url')
68
- }
69
- }
70
-
71
-
72
- function verifyClose (t) {
73
- return function () {
74
- t.ok(true, 'got close')
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert'
3
+ import { createMockServer } from 'ghutils/test-util'
4
+ import * as ghusers from './ghusers.js'
5
+
6
+ test('get user', async () => {
7
+ const auth = { token: 'test-token' }
8
+ const testData = { login: 'testuser', id: 1, name: 'Test User' }
9
+
10
+ const server = await createMockServer({ response: testData })
11
+ try {
12
+ const result = await ghusers.get(auth, 'testuser', {
13
+ _apiUrl: server.baseUrl
14
+ })
15
+ assert.deepStrictEqual(result, testData)
16
+ assert.ok(server.requests[0].url.includes('/users/testuser'))
17
+ assert.strictEqual(server.requests[0].headers.authorization, 'Bearer test-token')
18
+ } finally {
19
+ await server.close()
75
20
  }
76
- }
77
-
21
+ })
78
22
 
79
- function verifyData (t, data) {
80
- return function (err, _data) {
81
- t.notOk(err, 'no error')
82
- t.ok((data === '' && _data === '') || _data, 'got data')
83
- t.deepEqual(_data, data, 'got expected data')
23
+ test('auth header is correctly set', async () => {
24
+ const auth = { token: 'my-secret-token' }
25
+ const testData = { login: 'testuser' }
26
+
27
+ const server = await createMockServer({ response: testData })
28
+ try {
29
+ await ghusers.get(auth, 'testuser', { _apiUrl: server.baseUrl })
30
+ assert.strictEqual(server.requests[0].headers.authorization, 'Bearer my-secret-token')
31
+ assert.strictEqual(server.requests[0].headers.accept, 'application/vnd.github+json')
32
+ } finally {
33
+ await server.close()
84
34
  }
85
- }
86
-
87
-
88
- test('test get user', function (t) {
89
- t.plan(7)
90
-
91
- var auth = { user: 'authuser', token: 'authtoken' }
92
- , username = 'testuser'
93
- , testData = { login: username, test: 'data' }
94
- , server
95
-
96
- server = makeServer(testData)
97
- .on('ready', function () {
98
- ghusers.get(xtend(auth), username, verifyData(t, testData))
99
- })
100
- .on('request', verifyRequest(t, auth))
101
- .on('get', verifyUrl(t, [
102
- 'https://api.github.com/users/' + username
103
- ]))
104
- .on('close' , verifyClose(t))
105
35
  })
package/.jshintrc DELETED
@@ -1,59 +0,0 @@
1
- {
2
- "predef": [ ]
3
- , "bitwise": false
4
- , "camelcase": false
5
- , "curly": false
6
- , "eqeqeq": false
7
- , "forin": false
8
- , "immed": false
9
- , "latedef": false
10
- , "noarg": true
11
- , "noempty": true
12
- , "nonew": true
13
- , "plusplus": false
14
- , "quotmark": true
15
- , "regexp": false
16
- , "undef": true
17
- , "unused": true
18
- , "strict": false
19
- , "trailing": true
20
- , "maxlen": 120
21
- , "asi": true
22
- , "boss": true
23
- , "debug": true
24
- , "eqnull": true
25
- , "esnext": true
26
- , "evil": true
27
- , "expr": true
28
- , "funcscope": false
29
- , "globalstrict": false
30
- , "iterator": false
31
- , "lastsemic": true
32
- , "laxbreak": true
33
- , "laxcomma": true
34
- , "loopfunc": true
35
- , "multistr": false
36
- , "onecase": false
37
- , "proto": false
38
- , "regexdash": false
39
- , "scripturl": true
40
- , "smarttabs": false
41
- , "shadow": false
42
- , "sub": true
43
- , "supernew": false
44
- , "validthis": true
45
- , "browser": true
46
- , "couch": false
47
- , "devel": false
48
- , "dojo": false
49
- , "mootools": false
50
- , "node": true
51
- , "nonstandard": true
52
- , "prototypejs": false
53
- , "rhino": false
54
- , "worker": true
55
- , "wsh": false
56
- , "nomen": false
57
- , "onevar": false
58
- , "passfail": false
59
- }
package/.npmignore DELETED
@@ -1,2 +0,0 @@
1
- node_modules
2
- ex.js
package/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "0.10"
4
- branches:
5
- only:
6
- - master
7
- notifications:
8
- email:
9
- - rod@vagg.org
10
- script: npm test