├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .prettierrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── example ├── nuxt.config.js └── pages │ └── index.vue ├── husky.config.js ├── jest.config.js ├── lib ├── module.js └── plugin.js ├── package.json ├── renovate.json ├── test └── module.test.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | .nuxt 5 | coverage 6 | 7 | # Plugin 8 | lib/plugin.js 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | rules: { 8 | 'space-before-function-paren': 0 9 | }, 10 | extends: ['@nuxtjs'] 11 | } 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | jobs: 12 | ci: 13 | runs-on: ${{ matrix.os }} 14 | 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, windows-latest] 18 | node: [10, 12] 19 | 20 | steps: 21 | - uses: actions/setup-node@v1 22 | with: 23 | node-version: ${{ matrix.node }} 24 | 25 | - name: checkout 26 | uses: actions/checkout@master 27 | 28 | - name: cache node_modules 29 | uses: actions/cache@v1 30 | with: 31 | path: node_modules 32 | key: ${{ matrix.os }}-node-v${{ matrix.node }}-deps-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }} 33 | 34 | - name: Install dependencies 35 | if: steps.cache.outputs.cache-hit != 'true' 36 | run: yarn 37 | 38 | - name: Lint 39 | run: yarn lint 40 | 41 | - name: Test 42 | run: yarn test 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Coverage 47 | uses: codecov/codecov-action@v1 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .nuxt 6 | .vscode 7 | .DS_Store 8 | coverage 9 | dist 10 | .env -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.1.6](https://github.com/lindsaykwardell/nuxt-github-api/compare/v0.1.5...v0.1.6) (2020-11-12) 6 | 7 | ### [0.1.5](https://github.com/lindsaykwardell/nuxt-github-api/compare/v0.1.4...v0.1.5) (2020-09-06) 8 | 9 | 10 | ### Features 11 | 12 | * enabled passing variables to graphql query ([29048c4](https://github.com/lindsaykwardell/nuxt-github-api/commit/29048c490cd9fc5cc953194203f96e4e1aa10fb2)) 13 | 14 | ### [0.1.4](https://github.com/lindsaykwardell/nuxt-github-api/compare/v0.1.3...v0.1.4) (2020-09-06) 15 | 16 | 17 | ### Bug Fixes 18 | 19 | * removed isomorphic-fetch ([4b09599](https://github.com/lindsaykwardell/nuxt-github-api/commit/4b09599635cfb5a71c59dd7abc904769fa6f5077)) 20 | 21 | ### 0.1.3 (2020-09-06) 22 | 23 | 24 | ### Bug Fixes 25 | 26 | * adjusted readme to include github token ([aa3fd27](https://github.com/lindsaykwardell/nuxt-github-api/commit/aa3fd27cbe4bac099cc53a2b3085dedb6547ac12)) 27 | * attempting to correct ci ([7156fe2](https://github.com/lindsaykwardell/nuxt-github-api/commit/7156fe24de623713af4fcd4497ffa09a8276f74b)) 28 | * follow-up to fix ci ([9440ce7](https://github.com/lindsaykwardell/nuxt-github-api/commit/9440ce7155f34cef1f1281acfa5e1c63eafa6556)) 29 | * moving to env option ([fd11a02](https://github.com/lindsaykwardell/nuxt-github-api/commit/fd11a02c66898b39071cf0cef51139d30205fc43)) 30 | * run test using github token ([83599c3](https://github.com/lindsaykwardell/nuxt-github-api/commit/83599c3d4c71e265e8b50616f0d2df543bc34fa8)) 31 | * update links for badges ([73fcc19](https://github.com/lindsaykwardell/nuxt-github-api/commit/73fcc192653c797b8003400c0d84ba4d73d51bed)) 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Lindsay Wardell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nuxt-github-api 2 | 3 | [![npm version][npm-version-src]][npm-version-href] 4 | [![npm downloads][npm-downloads-src]][npm-downloads-href] 5 | [![Github Actions CI][github-actions-ci-src]][github-actions-ci-href] 6 | [![Codecov][codecov-src]][codecov-href] 7 | [![License][license-src]][license-href] 8 | 9 | Source plugin for pulling data into Nuxt from the official GitHub v4 [GraphQL API](https://developer.github.com/v4/). Data is fetched at build time, and can be used to create static assets. 10 | 11 | [📖 **Release Notes**](./CHANGELOG.md) 12 | 13 | ## Setup 14 | 15 | 1. Follow GitHub's guide to [generate a token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token). 16 | 2. Add this token to your environment variables (_PLEASE_ don't commit this token!!!) 17 | 3. Add `nuxt-github-api` dependency to your project 18 | 19 | ```bash 20 | yarn add nuxt-github-api # or npm install nuxt-github-api 21 | ``` 22 | 23 | 2. Add `nuxt-github-api` to the `modules` section of `nuxt.config.js` 24 | 25 | ```js 26 | { 27 | modules: [ 28 | // Simple usage 29 | 'nuxt-github-api', 30 | 31 | // With options 32 | [ 33 | 'nuxt-github-api', 34 | { 35 | // token: required by the GitHub API 36 | token: process.env.GITHUB_API_TOKEN, 37 | 38 | // graphQLQuery: defaults to a search query 39 | graphQLQuery: ` 40 | query GetUser($login: String!) { 41 | user(login: $login) { 42 | name 43 | avatarUrl 44 | bio 45 | isHireable 46 | } 47 | } 48 | `, 49 | 50 | // variables: Object which includes any GraphQL variables required by your query. 51 | variables: { 52 | login: 'lindsaykwardell' 53 | } 54 | } 55 | ] 56 | ], 57 | } 58 | ``` 59 | 60 | You can also pass the options as a separate key: 61 | 62 | ```js 63 | 64 | { 65 | github: { 66 | // token: required by the GitHub API 67 | token: process.env.GITHUB_API_TOKEN, 68 | 69 | // graphQLQuery: defaults to a search query 70 | graphQLQuery: ` 71 | query GetUser($login: String!) { 72 | user(login: $login) { 73 | name 74 | avatarUrl 75 | bio 76 | isHireable 77 | } 78 | } 79 | `, 80 | 81 | // variables: Object which includes any GraphQL variables required by your query. 82 | variables: { 83 | login: 'lindsaykwardell' 84 | } 85 | } 86 | } 87 | 88 | ``` 89 | 90 | In your Vue components, you can now access this data on `this.$github`. For example: 91 | 92 | ```vue 93 | 103 | 104 | 115 | ``` 116 | 117 | ## Development 118 | 119 | 1. Clone this repository 120 | 2. Install dependencies using `yarn install` or `npm install` 121 | 3. Create .env file at the root of the project. 122 | 4. Add variable: `GITHUB_TOKEN` 123 | 5. Start development server using `npm run dev` 124 | 125 | ## License 126 | 127 | [MIT License](./LICENSE) 128 | 129 | Copyright (c) Lindsay Wardell 130 | 131 | ## Tips and Tricks 132 | 133 | You'll probably want to use valid GraphQL queries. To help you, GitHub has a [Query Explorer](https://developer.github.com/v4/explorer/) with auto-completion. 134 | 135 | ![Query Explorer](https://user-images.githubusercontent.com/1187476/30273078-69695a10-96c5-11e7-90b8-7dc876cc214a.png) 136 | 137 | 138 | 139 | [npm-version-src]: https://img.shields.io/npm/v/nuxt-github-api/latest.svg 140 | [npm-version-href]: https://npmjs.com/package/nuxt-github-api 141 | [npm-downloads-src]: https://img.shields.io/npm/dt/nuxt-github-api.svg 142 | [npm-downloads-href]: https://npmjs.com/package/nuxt-github-api 143 | [github-actions-ci-src]: https://github.com/lindsaykwardell/nuxt-github-api/workflows/ci/badge.svg 144 | [github-actions-ci-href]: https://github.com/lindsaykwardell/nuxt-github-api/actions?query=workflow%3Aci 145 | [codecov-src]: https://img.shields.io/codecov/c/github/lindsaykwardell/nuxt-github-api.svg 146 | [codecov-href]: https://codecov.io/gh/lindsaykwardell/nuxt-github-api 147 | [license-src]: https://img.shields.io/npm/l/nuxt-github-api.svg 148 | [license-href]: https://npmjs.com/package/nuxt-github-api 149 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', { 5 | targets: { 6 | esmodules: true 7 | } 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@commitlint/config-conventional' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /example/nuxt.config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | const { resolve } = require('path') 3 | 4 | module.exports = { 5 | rootDir: resolve(__dirname, '..'), 6 | buildDir: resolve(__dirname, '.nuxt'), 7 | srcDir: __dirname, 8 | modules: [{ handler: require('../') }], 9 | githubApi: { 10 | token: process.env.GITHUB_TOKEN, 11 | graphQLQuery: ` 12 | query GetUser($login: String!) { 13 | user(login: $login) { 14 | name 15 | avatarUrl 16 | bio 17 | isHireable 18 | } 19 | } 20 | `, 21 | variables: { 22 | login: 'lindsaykwardell' 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /example/pages/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 26 | -------------------------------------------------------------------------------- /husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 4 | 'pre-commit': 'yarn lint', 5 | 'pre-push': 'yarn lint' 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'node', 3 | collectCoverage: true, 4 | collectCoverageFrom: [ 5 | 'lib/**/*.js', 6 | '!lib/plugin.js' 7 | ], 8 | moduleNameMapper: { 9 | '^~/(.*)$': '/lib/$1', 10 | '^~~$': '', 11 | '^@@$': '', 12 | '^@/(.*)$': '/lib/$1' 13 | }, 14 | transform: { 15 | '^.+\\.js$': 'babel-jest' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/module.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path') 2 | 3 | const defaultOptions = { 4 | token: null, 5 | graphQLQuery: `query ($nFirst: Int = 2, $q: String = "") { 6 | search(query: $q, type: ISSUE, first: $nFirst){ 7 | edges{ 8 | node{ 9 | ... on PullRequest{ 10 | title 11 | } 12 | } 13 | } 14 | } 15 | }`, 16 | variables: {} 17 | } 18 | 19 | module.exports = function nuxtGithubApi(opts = defaultOptions) { 20 | const { token, graphQLQuery, variables } = { 21 | ...defaultOptions, 22 | ...this.options.githubApi, 23 | ...opts 24 | } 25 | 26 | if (!token) { 27 | throw new Error('Missing GitHub API token!') 28 | } 29 | 30 | if (graphQLQuery.trim().indexOf('query') !== 0) { 31 | throw new Error('GitHub API queries must be wrapped in `query{}`.') 32 | } 33 | 34 | this.addPlugin({ 35 | src: resolve(__dirname, 'plugin.js'), 36 | options: { 37 | token, 38 | graphQLQuery, 39 | variables: JSON.stringify(variables) 40 | } 41 | }) 42 | } 43 | 44 | module.exports.meta = require('../package.json') 45 | -------------------------------------------------------------------------------- /lib/plugin.js: -------------------------------------------------------------------------------- 1 | const gql = async (url, query, variables, options) => { 2 | const res = await fetch(url, { 3 | ...options, 4 | body: JSON.stringify({ 5 | query, 6 | variables 7 | }) 8 | }) 9 | 10 | if (!res.ok) throw new Error(res.json()) 11 | 12 | const body = await res.json() 13 | 14 | if (body.errors) throw new Error(JSON.stringify(body.errors)) 15 | 16 | return body 17 | } 18 | 19 | const url = 'https://api.github.com/graphql' 20 | 21 | const fetchFromGitHub = (token, graphQLQuery, variables) => { 22 | return gql(url, graphQLQuery, variables, { 23 | method: 'POST', 24 | mode: 'cors', 25 | headers: { 26 | Authorization: `Bearer ${token}` 27 | } 28 | }) 29 | } 30 | 31 | export default async (context, inject) => { 32 | const { data } = await fetchFromGitHub( 33 | '<%= options.token %>', 34 | `<%= options.graphQLQuery %>`, 35 | JSON.parse('<%= options.variables %>') 36 | ) 37 | 38 | inject('github', data) 39 | 40 | context.$github = data 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-github-api", 3 | "version": "0.1.6", 4 | "description": "Nuxt module for GitHub v4 API", 5 | "author": "Lindsay Wardell", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/lindsaykwardell/nuxt-github-api.git" 9 | }, 10 | "license": "MIT", 11 | "contributors": [ 12 | { 13 | "name": "Lindsay Wardell" 14 | } 15 | ], 16 | "files": [ 17 | "lib/**/*" 18 | ], 19 | "main": "lib/module.js", 20 | "scripts": { 21 | "dev": "nuxt example", 22 | "lint": "eslint --ext .js,.vue .", 23 | "release": "yarn test && standard-version && git push --follow-tags && npm publish", 24 | "test": "yarn lint && jest" 25 | }, 26 | "dependencies": {}, 27 | "devDependencies": { 28 | "@babel/core": "latest", 29 | "@babel/preset-env": "latest", 30 | "@commitlint/cli": "latest", 31 | "@commitlint/config-conventional": "latest", 32 | "@nuxtjs/eslint-config": "latest", 33 | "@nuxtjs/module-test-utils": "latest", 34 | "babel-eslint": "latest", 35 | "babel-jest": "latest", 36 | "cross-env": "^7.0.2", 37 | "dotenv": "^8.2.0", 38 | "eslint": "latest", 39 | "husky": "latest", 40 | "jest": "latest", 41 | "nuxt-edge": "latest", 42 | "standard-version": "latest" 43 | }, 44 | "publishConfig": { 45 | "access": "public" 46 | }, 47 | "keywords": [ 48 | "nuxt", 49 | "nuxt-module", 50 | "github" 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@nuxtjs" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /test/module.test.js: -------------------------------------------------------------------------------- 1 | const { setup, loadConfig, get } = require('@nuxtjs/module-test-utils') 2 | 3 | describe('module', () => { 4 | let nuxt 5 | 6 | beforeAll(async () => { 7 | ;({ nuxt } = await setup(loadConfig(__dirname, '../../example'))) 8 | }, 60000) 9 | 10 | afterAll(async () => { 11 | await nuxt.close() 12 | }) 13 | 14 | test('render', async () => { 15 | // ;({ nuxt } = await setup(loadConfig(__dirname, '../../example'))) 16 | 17 | const html = await get('/') 18 | expect(html).toContain('Lindsay Wardell') 19 | }) 20 | 21 | test('throws error when no Github token is present', async () => { 22 | try { 23 | ;({ nuxt } = await setup( 24 | loadConfig(__dirname, '../../example', { 25 | githubApi: { 26 | token: null 27 | } 28 | }) 29 | )) 30 | } catch (err) { 31 | expect(err.toString().includes('Missing GitHub API token!')).toBe(true) 32 | } 33 | }) 34 | 35 | test('throws error when query is invalid', async () => { 36 | try { 37 | ;({ nuxt } = await setup( 38 | loadConfig(__dirname, '../../example', { 39 | githubApi: { 40 | token: process.env.GITHUB_TOKEN, 41 | graphQLQuery: 'invalid query' 42 | } 43 | }) 44 | )) 45 | } catch (err) { 46 | expect(err.toString().includes('GitHub API queries must be wrapped in `query{}`')).toBe(true) 47 | } 48 | }) 49 | }) 50 | --------------------------------------------------------------------------------