From b6569848d78d5ca7d5dfb17d2ec13001c583016a Mon Sep 17 00:00:00 2001 From: Michael Murray Date: Thu, 21 Sep 2017 12:21:45 -0700 Subject: [PATCH 1/4] Add intregration to google API --- .env | 11 ++++++++++- index.js | 19 ++++++++++--------- package.json | 6 +++++- src/models/Sheets.js | 30 +++++++++++++++++++++++++----- src/models/Spreadsheet.js | 24 +++++++++++++++--------- src/models/User.js | 5 ----- src/resolvers/RootResolver.js | 7 ++----- src/schema.js | 9 +++------ test/Spreadsheet.test.js | 10 +++------- 9 files changed, 73 insertions(+), 48 deletions(-) delete mode 100644 src/models/User.js diff --git a/.env b/.env index 8b13789..ff2b37a 100644 --- a/.env +++ b/.env @@ -1 +1,10 @@ - +GOOGLE_SHEETS_CLIENT_ID=815587375882-jkchj47keoir66kuc1vg85tuvpi71rie.apps.googleusercontent.com +GOOGLE_SHEETS_CLIENT_SECRET=s_UN_vXIPVEY1_wXAk1pyX5K +FRONT_END_BASE_URL=http://localhost:3000 +TKN= +GOOGLE_SHEETS_PROFILE_ID= +SESSION_KEY1=9a3ddb5dddd8331dbc1bd29b15c8210f30e72fa695adcbafb2848f436c03f43eb7397efa95da43927613a0c1def8bd6b +SESSION_KEY2=2ff5b9865570e7f8ecc6653d5cc7f559edb8df3ad235663ebdcf5770a727cf8bb4dc9f924c7919b38e2b1033f4d935d7 +SECRET=RONAN the BARBARIAN +API_BASE_URL=http://localhost:8003 +API_KEY=AIzaSyCPew8DFC4tF64YfYajB9t9fXwZ6qlRECQ diff --git a/index.js b/index.js index 1b694b9..2a5550d 100644 --- a/index.js +++ b/index.js @@ -10,12 +10,13 @@ const root = require('./src/resolvers/RootResolver'); const schema = require('./src/schema'); const partials = require('express-partials'); const cors = require('cors'); + const app = express(); const PORT = process.env.PORT || 8000; const GOOGLE_CLIENT_ID = process.env.GOOGLE_SHEETS_CLIENT_ID; const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_SHEETS_CLIENT_SECRET; -const API_BASE_URL= process.env.API_BASE_URL; +const API_BASE_URL = process.env.API_BASE_URL; /* eslint-disable no-unused-vars */ // NOTE these variables will be used once the OAuth strategy begins, not before const CALLBACK_URL = process.env.GOOGLE_SHEETS_URL; @@ -70,14 +71,14 @@ app.get('/auth/google/callback', res.redirect(process.env.FRONT_END_BASE_URL); }); - app.use( - '/graphql', - graphqlHTTP({ - schema, - rootValue: root, - graphiql: true, - }), - ); +app.use( + '/graphql', + graphqlHTTP({ + schema, + rootValue: root, + graphiql: true, + }), +); app.use('/', (req, res) => { res.sendStatus(200); diff --git a/package.json b/package.json index b6e8755..0c24f23 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,13 @@ "express-partials": "0.3.0", "express-session": "1.15.5", "graphql": "0.10.5", + "graphql-type-json": "^0.1.4", + "isomorphic-fetch": "^2.2.1", + "node-fetch": "^1.7.3", "nodemon": "1.11.0", "passport": "0.3.2", - "passport-google-oauth20": "1.0.0" + "passport-google-oauth20": "1.0.0", + "whatwg-fetch": "^2.0.3" }, "devDependencies": { "chai": "4.1.0", diff --git a/src/models/Sheets.js b/src/models/Sheets.js index 8c671c8..ff979f3 100644 --- a/src/models/Sheets.js +++ b/src/models/Sheets.js @@ -1,17 +1,37 @@ -const data = require('../mockdata'); const Sheet = require('./Sheet'); +const fetch = require('isomorphic-fetch'); /* eslint-disable class-methods-use-this */ +function getJson(response) { + return response.json(); +} +function createSheetInstances(sheets) { + return sheets.map(sheet => new Sheet(sheet)); +} class Sheets { constructor({ spreadsheetId, sheetName }) { this.spreadsheetId = spreadsheetId; this.sheetName = sheetName; + this.sheetUrl = `https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}/values/${sheetName}!A1:ZZ?access_token=${process.env.TKN}`; + this.spreadSheetUrl = `https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}?access_token=${process.env.TKN}`; } get sheets() { - return this.sheetName ? [new Sheet(data.SHEET1_DATA)] : this.getAllUserSheets(); + return this.sheetName ? this.getSheetByName() : this.getAllUserSheets(); + } + getSheetByName() { + return fetch(this.sheetUrl) + .then(response => getJson(response)) + .then(data => [new Sheet(data)]); } - getAllUserSheets() { - const sheetDataArr = [data.SHEET1_DATA, data.SHEET2_DATA]; - return sheetDataArr.map(sheetData => new Sheet(sheetData)); + async getAllUserSheets() { + return fetch(this.spreadSheetUrl) + .then(getJson) + .then(response => + response.sheets.map(sheet => sheet.properties.title)) + .then(sheetNames => sheetNames.map(sheetName => fetch(`https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}/values/${sheetName}!A1:ZZ?access_token=${process.env.TKN}`))) + .then(promiseArray => Promise.all(promiseArray)) + .then(responses => responses.map(response => response.json())) + .then(responses => Promise.all(responses)) + .then(createSheetInstances); } } diff --git a/src/models/Spreadsheet.js b/src/models/Spreadsheet.js index a18e4c3..147872c 100644 --- a/src/models/Spreadsheet.js +++ b/src/models/Spreadsheet.js @@ -1,17 +1,23 @@ -const data = require('../mockdata'); -const Sheet = require('./Sheet'); -/* eslint-disable class-methods-use-this */ - +const fetch = require('isomorphic-fetch'); +/* eslint-disable class-methods-use-this */ +function getJson(response) { + return response.json(); +} class Spreadsheet { - constructor(spreadsheetId) { + constructor({ spreadsheetId }) { this.spreadsheetId = spreadsheetId; - this.spreadSheetData = data.SPREADSHEET_DATA; + this.spreadSheetUrl = `https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}?access_token=${process.env.TKN}`; + } + get spreadSheetName() { + return fetch(this.spreadSheetUrl) + .then(response => getJson(response)) + .then(data => data.properties.title); } get sheets() { - // const sheetNames = this.spreadSheetData.sheets.map(sheet => sheet.properties.title); - const sheetDataArr = [data.SHEET1_DATA, data.SHEET2_DATA]; - return sheetDataArr.map(sheetData => new Sheet(sheetData)); + return fetch(this.spreadSheetUrl) + .then(response => getJson(response)) + .then(data => data.sheets.map(sheet => sheet.properties.title)); } } diff --git a/src/models/User.js b/src/models/User.js deleted file mode 100644 index ac95175..0000000 --- a/src/models/User.js +++ /dev/null @@ -1,5 +0,0 @@ -class User { - -} - -module.exports = User; diff --git a/src/resolvers/RootResolver.js b/src/resolvers/RootResolver.js index 6869863..a4fcf6c 100644 --- a/src/resolvers/RootResolver.js +++ b/src/resolvers/RootResolver.js @@ -1,12 +1,9 @@ -const User = require('../models/User'); + const Spreadsheet = require('../models/Spreadsheet'); const Sheets = require('../models/Sheets'); -const root = { - user(userName) { - return new User(userName); - }, +const root = { sheets(spreadsheetId, sheetName) { return new Sheets(spreadsheetId, sheetName); }, diff --git a/src/schema.js b/src/schema.js index 15b7d80..9ff5c1b 100644 --- a/src/schema.js +++ b/src/schema.js @@ -1,17 +1,15 @@ const { buildSchema } = require('graphql'); + const schema = buildSchema(` - type User { - userName: String! - } type Spreadsheet { spreadsheetId: String - sheets: [Sheet] + spreadSheetName: String + sheets: [String] } type Sheets { spreadsheetId: String - sheetName: String sheets: [Sheet] } @@ -23,7 +21,6 @@ const schema = buildSchema(` } type Query { - user(userName: String): User sheets(spreadsheetId: String, sheetName: String): Sheets spreadsheet(spreadsheetId: String): Spreadsheet } diff --git a/test/Spreadsheet.test.js b/test/Spreadsheet.test.js index 26ad35f..23fbdc3 100644 --- a/test/Spreadsheet.test.js +++ b/test/Spreadsheet.test.js @@ -1,20 +1,16 @@ /* eslint-disable no-undef, no-unused-expressions */ const { expect } = require('chai'); const Spreadsheet = require('../src/models/Spreadsheet'); -const Sheet = require('../src/models/Sheet'); - // TODO: ALL tests will need to be refactored when the backend is making calls // to the Google API describe('Spreadsheet model', () => { - const spreadsheet = new Spreadsheet('1UcfQsQGTAAtjvyxv948z3hf0qiUnMNZF90-GcD7MF9g'); - it('should work', () => { expect(true).to.be.ok; }); - it('accepts spreadsheetId as a passed in argument', () => { - const sheets = spreadsheet.sheets; - expect(sheets[0]).to.be.an.instanceof(Sheet); + it('should take in a spreadsheetId', () => { + const spreadsheet = new Spreadsheet({ spreadsheetId: '1UcfQsQGTAAtjvyxv948z3hf0qiUnMNZF90-GcD7MF9g' }); + expect(spreadsheet.spreadsheetId).to.equal('1UcfQsQGTAAtjvyxv948z3hf0qiUnMNZF90-GcD7MF9g'); }); }); From 67624d3a862ee15fa4aa7edb4c42961e55d95ae1 Mon Sep 17 00:00:00 2001 From: Michael Murray Date: Thu, 21 Sep 2017 14:28:30 -0700 Subject: [PATCH 2/4] Remove .env --- .env | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index ff2b37a..0000000 --- a/.env +++ /dev/null @@ -1,10 +0,0 @@ -GOOGLE_SHEETS_CLIENT_ID=815587375882-jkchj47keoir66kuc1vg85tuvpi71rie.apps.googleusercontent.com -GOOGLE_SHEETS_CLIENT_SECRET=s_UN_vXIPVEY1_wXAk1pyX5K -FRONT_END_BASE_URL=http://localhost:3000 -TKN= -GOOGLE_SHEETS_PROFILE_ID= -SESSION_KEY1=9a3ddb5dddd8331dbc1bd29b15c8210f30e72fa695adcbafb2848f436c03f43eb7397efa95da43927613a0c1def8bd6b -SESSION_KEY2=2ff5b9865570e7f8ecc6653d5cc7f559edb8df3ad235663ebdcf5770a727cf8bb4dc9f924c7919b38e2b1033f4d935d7 -SECRET=RONAN the BARBARIAN -API_BASE_URL=http://localhost:8003 -API_KEY=AIzaSyCPew8DFC4tF64YfYajB9t9fXwZ6qlRECQ From 910ca32a56e20694358f8ece7e725fa0e4190d35 Mon Sep 17 00:00:00 2001 From: Michael Murray Date: Thu, 21 Sep 2017 14:50:19 -0700 Subject: [PATCH 3/4] Add .catch statements --- package.json | 1 - src/models/Sheets.js | 8 +++++--- src/models/Spreadsheet.js | 6 ++++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 3738ace..f913d12 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ }, "devDependencies": { "chai": "4.1.0", - "dotenv": "4.0.0", "mocha": "3.4.2", "nock": "9.0.14", "sinon": "3.2.1", diff --git a/src/models/Sheets.js b/src/models/Sheets.js index ff979f3..3e859c7 100644 --- a/src/models/Sheets.js +++ b/src/models/Sheets.js @@ -20,9 +20,10 @@ class Sheets { getSheetByName() { return fetch(this.sheetUrl) .then(response => getJson(response)) - .then(data => [new Sheet(data)]); + .then(data => [new Sheet(data)]) + .catch(err => err); } - async getAllUserSheets() { + getAllUserSheets() { return fetch(this.spreadSheetUrl) .then(getJson) .then(response => @@ -31,7 +32,8 @@ class Sheets { .then(promiseArray => Promise.all(promiseArray)) .then(responses => responses.map(response => response.json())) .then(responses => Promise.all(responses)) - .then(createSheetInstances); + .then(createSheetInstances) + .catch(err => err); } } diff --git a/src/models/Spreadsheet.js b/src/models/Spreadsheet.js index 147872c..464486a 100644 --- a/src/models/Spreadsheet.js +++ b/src/models/Spreadsheet.js @@ -12,12 +12,14 @@ class Spreadsheet { get spreadSheetName() { return fetch(this.spreadSheetUrl) .then(response => getJson(response)) - .then(data => data.properties.title); + .then(data => data.properties.title) + .catch(err => err); } get sheets() { return fetch(this.spreadSheetUrl) .then(response => getJson(response)) - .then(data => data.sheets.map(sheet => sheet.properties.title)); + .then(data => data.sheets.map(sheet => sheet.properties.title)) + .catch(err => err); } } From 9e7482ff715d7e6d4dde84e61c8ccf9a0b347117 Mon Sep 17 00:00:00 2001 From: Michael Murray Date: Fri, 22 Sep 2017 14:43:07 -0700 Subject: [PATCH 4/4] Fix getAllSheets --- index.js | 13 ++++++------- src/models/Sheets.js | 8 ++++---- src/schema.js | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index 12b0639..5e4c691 100644 --- a/index.js +++ b/index.js @@ -20,7 +20,6 @@ const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_SHEETS_CLIENT_SECRET; const API_BASE_URL = process.env.API_BASE_URL; /* eslint-disable no-unused-vars */ // NOTE these variables will be used once the OAuth strategy begins, not before -const CALLBACK_URL = process.env.GOOGLE_SHEETS_URL; const PROFILE_ID = process.env.GOOGLE_SHEETS_PROFILE_ID; app.use(morgan('combined')); @@ -54,13 +53,13 @@ passport.use(new GoogleStrategy({ callbackURL: `${API_BASE_URL}/auth/google/callback`, }, - ((accessToken, refreshToken, profile, done) => { - process.env.TKN = accessToken; - process.env.PROFILE_ID = profile.id; - process.env.USERNAME = profile.displayName; +((accessToken, refreshToken, profile, done) => { + process.env.TKN = accessToken; + process.env.PROFILE_ID = profile.id; + process.env.USERNAME = profile.displayName; - done(null, profile); - }), + done(null, profile); +}), )); app.get('/auth/google', diff --git a/src/models/Sheets.js b/src/models/Sheets.js index 3e859c7..6206203 100644 --- a/src/models/Sheets.js +++ b/src/models/Sheets.js @@ -26,14 +26,14 @@ class Sheets { getAllUserSheets() { return fetch(this.spreadSheetUrl) .then(getJson) - .then(response => - response.sheets.map(sheet => sheet.properties.title)) - .then(sheetNames => sheetNames.map(sheetName => fetch(`https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}/values/${sheetName}!A1:ZZ?access_token=${process.env.TKN}`))) + .then(response => response.sheets.map(sheet => sheet.properties.title)) + .then(sheetNames => sheetNames.map(sheetName => fetch(`https://sheets.googleapis.com/v4/spreadsheets/${this.spreadsheetId}/values/${sheetName}!A1:ZZ?access_token=${process.env.TKN}`), + )) .then(promiseArray => Promise.all(promiseArray)) .then(responses => responses.map(response => response.json())) .then(responses => Promise.all(responses)) .then(createSheetInstances) - .catch(err => err); + .catch(err => console.log(err)); } } diff --git a/src/schema.js b/src/schema.js index 9ff5c1b..0cbc3d4 100644 --- a/src/schema.js +++ b/src/schema.js @@ -14,10 +14,10 @@ const schema = buildSchema(` } type Sheet { - sheetName: String range: String majorDimension: String values: [[String]] + sheetName: String } type Query {