├── index.js ├── .gitignore ├── .babelrc ├── .npmignore ├── package.json ├── src └── gatsby-node.js └── README.md /index.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.js 2 | !index.js 3 | yarn.lock 4 | tests 5 | node_modules 6 | .vscode -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "babel-preset-gatsby-package", 5 | { 6 | "corejs": 3 7 | } 8 | ] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | *.un~ 29 | yarn.lock 30 | src 31 | flow-typed 32 | coverage 33 | decls 34 | examples -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-source-google-sheet", 3 | "version": "2.0.0", 4 | "description": "Gatsby source plugin for consuming Google Sheets data", 5 | "main": "index.js", 6 | "homepage": "https://github.com/aendrew/gatsby-source-google-sheet", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/aendrew/gatsby-source-google-sheet.git" 10 | }, 11 | "scripts": { 12 | "build": "babel src --out-dir . --ignore __tests__", 13 | "watch": "babel -w src --out-dir . --ignore __tests__", 14 | "prepare": "cross-env NODE_ENV=production npm run build" 15 | }, 16 | "keywords": ["gatsby", "gatsby-plugin", "Google Sheets"], 17 | "author": "Ændrew Rininsland ", 18 | "license": "ISC", 19 | "dependencies": { 20 | "@babel/runtime": "^7.4.5", 21 | "gatsby-node-helpers": "^0.3.0", 22 | "google-spreadsheet": "^2.0.4" 23 | }, 24 | "devDependencies": { 25 | "@babel/cli": "^7.4.4", 26 | "@babel/core": "^7.4.5", 27 | "babel-preset-gatsby-package": "^0.1.4", 28 | "cross-env": "^5.2.0", 29 | "prettier": "^1.17.1", 30 | "core-js": "^3.1.3" 31 | }, 32 | "peerDependencies": { 33 | "gatsby": ">=1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/gatsby-node.js: -------------------------------------------------------------------------------- 1 | // gatsby-node.js 2 | import GoogleSpreadsheet from "google-spreadsheet"; 3 | import createNodeHelpers from "gatsby-node-helpers"; 4 | 5 | const { 6 | createNodeFactory, 7 | } = createNodeHelpers({ 8 | typePrefix: `GoogleSheet` 9 | }); 10 | 11 | 12 | exports.sourceNodes = async ({ boundActionCreators }, pluginOptions) => { 13 | const { createNode } = boundActionCreators; 14 | 15 | const rootName = pluginOptions.rootName || "Sheet"; 16 | 17 | const RootNode = createNodeFactory(rootName); 18 | 19 | const doc = new GoogleSpreadsheet(pluginOptions.spreadsheetKey); 20 | 21 | if (pluginOptions.creds) { 22 | await new Promise(resolve => 23 | doc.useServiceAccountAuth(pluginOptions.creds, resolve) 24 | ); 25 | } 26 | 27 | const worksheets = await new Promise((resolve, reject) => 28 | doc.getInfo((err, info) => { 29 | if (err || !info.worksheets.length) reject(err); 30 | resolve(info.worksheets); 31 | }) 32 | ); 33 | 34 | const items = await worksheets.reduce(async (acc, sheet) => { 35 | const rows = await new Promise((resolve, reject) => { 36 | sheet.getRows((err, rows) => { 37 | if (err) reject(err); 38 | resolve(rows); 39 | }); 40 | }); 41 | 42 | return (await acc).concat(rows); 43 | }, Promise.resolve([])); 44 | 45 | const rows = items.forEach(item => { 46 | const itemNode = RootNode(item); 47 | createNode(itemNode); 48 | }); 49 | }; 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *Update:* Do you _really_ want to use Gatsby? https://twitter.com/tesseralis/status/1293649007739191296 2 | 3 | # gatsby-source-google-sheets 4 | 5 | Source plugin for pulling data into Gatsby from a Google Sheets document 6 | 7 | ## A note on versions 8 | 9 | I haven't really used this very extensively lately but have tried to upgrade it 10 | for Gatsby 2.x. 11 | 12 | * If using Gatsby 1.x, do `npm i gatsby-source-google-sheet@1` 13 | * If using Gatsby 2.x+, do `npm i gatsby-source-google-sheet@2` 14 | 15 | ## How to use 16 | 17 | ```javascript 18 | // In your gatsby-config.js 19 | module.exports = { 20 | plugins: [ 21 | /* 22 | * Gatsby's data processing layer begins with “source” plugins. Here we 23 | * setup the site to pull data from a particular Google Sheet 24 | */ 25 | { 26 | resolve: `gatsby-source-google-sheet`, 27 | options: { 28 | // For protected spreadsheets you can use two-legged OAuth as described here: 29 | // https://www.npmjs.com/package/google-spreadsheet#service-account-recommended-method 30 | creds: { 31 | client_email: `yourserviceaccountemailhere@google.com`, 32 | private_key: `` 33 | }, 34 | // This is the bit after "/d/" and before "/edit" in the URL of a 35 | // Google Sheets document. I.e., 36 | // https://docs.google.com/spreadsheets/d/1ec1bO25bbEL4pdZjhlV3AppMtnO65D0ZI8fXy4z47Dw/edit#gid=0 37 | spreadsheetKey: `1ec1bO25bbEL4pdZjhlV3AppMtnO65D0ZI8fXy4z47Dw`, 38 | rootName: "RootName" // default is Sheet 39 | } 40 | } 41 | ] 42 | }; 43 | ``` 44 | 45 | ##### With .env (if you make your code public) 46 | 47 | 1. Run `npm install dotenv --save-dev` 48 | 49 | 2. Create `.env` in the root folder and fill with the credentials 50 | 51 | ``` 52 | GS_CLIENT_EMAIL= 53 | GS_PRIVATE_KEY= 54 | ``` 55 | 56 | 3. Add `require('dotenv').config()` on top of _gatsby-config.js_, and edit the creds object 57 | 58 | ```javascript 59 | creds: { 60 | client_email: process.env.GS_CLIENT_EMAIL || ``, 61 | private_key: process.env.GS_PRIVATE_KEY.replace(/\\n/g, '\n') || `` 62 | } 63 | ``` 64 | 65 | ## Plugin options 66 | 67 | * **creds**: Object containing `client_email` and `private_key`, for non-public sheets. 68 | * **spreadsheetKey**: The key of the spreadsheet you want to consume via GraphQL. 69 | 70 | ## How to query your spreadsheet data using GraphQL 71 | 72 | Below is a sample query for fetching three columns in a spreadsheet. 73 | 74 | ```graphql 75 | query GetGoogleSheetsColumns { 76 | allGoogleSheet$rootName { 77 | edges { 78 | node { 79 | col1 80 | col2 81 | col3 82 | } 83 | } 84 | } 85 | } 86 | ``` 87 | --------------------------------------------------------------------------------