Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"ecmaVersion": 2018
},
"rules": {
"global-require": 0
"global-require": 0,
"import/no-extraneous-dependencies": 0
}
}
}
2 changes: 2 additions & 0 deletions scripts/createTestData.js
Original file line number Diff line number Diff line change
@@ -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(() => {
Expand Down
2 changes: 2 additions & 0 deletions scripts/dropTables.js
Original file line number Diff line number Diff line change
@@ -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(() => {
Expand Down
11 changes: 6 additions & 5 deletions src/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down
50 changes: 40 additions & 10 deletions src/fetcher.js
Original file line number Diff line number Diff line change
@@ -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');


Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 = {
Expand Down
12 changes: 11 additions & 1 deletion src/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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,
Expand Down
20 changes: 15 additions & 5 deletions src/schema/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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',
},
},
});

Expand Down
25 changes: 24 additions & 1 deletion src/schema/weather.js
Original file line number Diff line number Diff line change
@@ -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 = {
Expand Down