From d884ddd52299961449a4a43699c29744f702db34 Mon Sep 17 00:00:00 2001 From: Peter Czibik Date: Fri, 20 Sep 2019 13:58:29 +0200 Subject: [PATCH] Task_4_Done --- .eslintrc.json | 5 ++-- scripts/createTestData.js | 2 ++ scripts/dropTables.js | 2 ++ src/db.js | 11 +++++---- src/fetcher.js | 50 +++++++++++++++++++++++++++++++-------- src/schema.js | 12 +++++++++- src/schema/user.js | 20 ++++++++++++---- src/schema/weather.js | 25 +++++++++++++++++++- 8 files changed, 103 insertions(+), 24 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c72d0c6..77ac33c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,6 +16,7 @@ "ecmaVersion": 2018 }, "rules": { - "global-require": 0 + "global-require": 0, + "import/no-extraneous-dependencies": 0 } -} \ No newline at end of file +} diff --git a/scripts/createTestData.js b/scripts/createTestData.js index a841670..27c6a55 100755 --- a/scripts/createTestData.js +++ b/scripts/createTestData.js @@ -1,6 +1,8 @@ #!/usr/bin/env node /* eslint-disable no-console */ +require('dotenv/config'); + const db = require('../src/db'); Promise.all(db.createTables()).then(() => { diff --git a/scripts/dropTables.js b/scripts/dropTables.js index c09e742..dcbef69 100755 --- a/scripts/dropTables.js +++ b/scripts/dropTables.js @@ -1,6 +1,8 @@ #!/usr/bin/env node /* eslint-disable no-console */ +require('dotenv/config'); + const db = require('../src/db'); Promise.all(db.dropTables()).then(() => { diff --git a/src/db.js b/src/db.js index 2679ddc..50a62bb 100644 --- a/src/db.js +++ b/src/db.js @@ -25,7 +25,8 @@ const createTables = () => { name VARCHAR(30) NOT NULL, username VARCHAR(30) NOT NULL, email VARCHAR(30) NOT NULL UNIQUE, - password_digest VARCHAR(100) NOT NULL + password_digest VARCHAR(100) NOT NULL, + location VARCHAR(100) )`, `CREATE TABLE IF NOT EXISTS posts( id UUID PRIMARY KEY, @@ -60,12 +61,12 @@ const dropTables = () => { const createTestData = () => { // password for test user: password const testDataQueries = [ - `INSERT INTO users(id, name, username, email, password_digest) - VALUES('8aaf37cf-94c9-4c6a-b566-0265ce34b58c', 'Tyler', 'tyler1337', 'tyler@risingstack.com', '$2b$10$yv9DxXTpvBmBYKu8rXoSIONn3BZB5/jQRDPMKt/YUAq8eTYoXGwKu') + `INSERT INTO users(id, name, username, email, password_digest, location) + VALUES('8aaf37cf-94c9-4c6a-b566-0265ce34b58c', 'Tyler', 'tyler1337', 'tyler@risingstack.com', '$2b$10$yv9DxXTpvBmBYKu8rXoSIONn3BZB5/jQRDPMKt/YUAq8eTYoXGwKu', 'Budapest') RETURNING * `, - `INSERT INTO users(id, name, username, email, password_digest) - VALUES('8aaf37cf-94c9-4c6a-b566-0265ce34b68c', 'Marla', 'marlaSinger', 'marla@risingstack.com', '$2b$10$yv9DxXTpvBmBYKu8rXoSIONn3BZB5/jQRDPMKt/YUAq8eTYoXGwKu') + `INSERT INTO users(id, name, username, email, password_digest, location) + VALUES('8aaf37cf-94c9-4c6a-b566-0265ce34b68c', 'Marla', 'marlaSinger', 'marla@risingstack.com', '$2b$10$yv9DxXTpvBmBYKu8rXoSIONn3BZB5/jQRDPMKt/YUAq8eTYoXGwKu', 'London') RETURNING * `, `INSERT INTO posts(id, title, description, content, author, timestamp) diff --git a/src/fetcher.js b/src/fetcher.js index 4406286..468707a 100644 --- a/src/fetcher.js +++ b/src/fetcher.js @@ -1,7 +1,11 @@ +const querystring = require('querystring'); + const bcrypt = require('bcrypt'); const { get } = require('lodash'); const uuid = require('uuidv4').default; +const axios = require('axios'); +const config = require('./config'); const db = require('./db'); @@ -92,12 +96,12 @@ const hashPassword = (password) => new Promise((resolve, reject) => ( const createUser = async (args) => { const { - password, name, username, email, + password, name, username, email, location, } = get(args, 'input', {}); const hashedPassword = await hashPassword(password); const { rows } = await db.query({ - text: 'INSERT INTO users(id, name, username, email, password_digest) VALUES($1, $2, $3, $4, $5) RETURNING *', - values: [uuid(), name, username, email, hashedPassword], + text: 'INSERT INTO users(id, name, username, email, password_digest, location) VALUES($1, $2, $3, $4, $5, $6) RETURNING *', + values: [uuid(), name, username, email, hashedPassword, location], }); const user = rows[0]; delete user.password_digest; @@ -125,13 +129,39 @@ const createComment = async (args) => { }; -// TODO fire a request to the open weather API to fetch the today's weather -// https://api.openweathermap.org/data/2.5/weather -// "config.openWeatherMapAPIKey" should contain your API key from the environment -// Make sure you only return items that you have declared in your schema! -function getWeather() { - // eslint-disable-next-line no-console - console.log('JS Conf Budapest 2019!'); +async function getWeather({ location }) { + const APPID = config.openWeatherMapAPIKey; + const query = querystring.stringify({ + q: location, + units: 'metric', + APPID, + }); + + const url = new URL('https://api.openweathermap.org/data/2.5/weather'); + url.search = query; + + const { data } = await axios + .get(url.toString()); + + const { + coord: { + lat, + lon, + }, + main: { + humidity, + temp, + pressure, + }, + } = data; + + return { + lat, + lon, + humidity, + pressure, + temp, + }; } module.exports = { diff --git a/src/schema.js b/src/schema.js index 6ab2f61..463021e 100644 --- a/src/schema.js +++ b/src/schema.js @@ -10,8 +10,12 @@ const { const { getHello, resolveQuery, + getWeather, signin, } = require('./fetcher'); +const { + Weather, +} = require('./schema/weather'); const { UserConnection, UserFieldFilter, UserFieldOrder, UserMutations, User, } = require('./schema/user'); @@ -37,8 +41,14 @@ const queryType = new GraphQLObjectType({ }, resolve: (_, args) => signin(args), }, - // TODO create a top level weather resolver that accepts a location parameter weather: { + type: Weather, + args: { + location: { + type: new GraphQLNonNull(GraphQLString), + }, + }, + resolve: (_, args) => getWeather(args), }, users: { type: UserConnection, diff --git a/src/schema/user.js b/src/schema/user.js index 3ba4bcb..9ac54f1 100644 --- a/src/schema/user.js +++ b/src/schema/user.js @@ -10,7 +10,8 @@ const { } = require('graphql'); const { get } = require('lodash'); -const { resolveQuery, createUser } = require('../fetcher'); +const { Weather } = require('./weather'); +const { resolveQuery, createUser, getWeather } = require('../fetcher'); const { Node, PageInfo, FilterOperation, OrderDirection, } = require('./common'); @@ -49,10 +50,15 @@ const User = new GraphQLObjectType({ interfaces: [Node], isTypeOf: (value) => value instanceof Object, fields: { - id: { type: GraphQLID }, - name: { type: GraphQLString }, - username: { type: GraphQLString }, - email: { type: GraphQLString }, + id: { type: new GraphQLNonNull(GraphQLID) }, + name: { type: new GraphQLNonNull(GraphQLString) }, + username: { type: new GraphQLNonNull(GraphQLString) }, + email: { type: new GraphQLNonNull(GraphQLString) }, + location: { type: GraphQLString }, + weather: { + type: Weather, + resolve: ({ location }) => (location ? getWeather({ location }) : {}), + }, posts: { type: PostConnection, args: { @@ -116,6 +122,10 @@ const CreateUserInput = new GraphQLInputObjectType({ username: { type: new GraphQLNonNull(GraphQLString) }, email: { type: new GraphQLNonNull(GraphQLString) }, password: { type: new GraphQLNonNull(GraphQLString) }, + location: { + type: GraphQLString, + defaultValue: 'Budapest', + }, }, }); diff --git a/src/schema/weather.js b/src/schema/weather.js index a170103..62e84e3 100644 --- a/src/schema/weather.js +++ b/src/schema/weather.js @@ -1,9 +1,32 @@ const { GraphQLObjectType, + GraphQLString, } = require('graphql'); -// TODO (1) Write the weather schema const Weather = new GraphQLObjectType({ + name: 'Weather', + fields: { + lat: { + type: GraphQLString, + description: 'The latitude of the requested location', + }, + lon: { + type: GraphQLString, + description: 'The longitute of the requested location', + }, + temp: { + type: GraphQLString, + description: 'Temperature in Celsius degrees', + }, + humidity: { + type: GraphQLString, + description: 'Humidity in %', + }, + pressure: { + type: GraphQLString, + description: 'Atmospheric pressure in hPa', + }, + }, }); module.exports = {