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 = {