Skip to content

Commit

Permalink
Finish dojo implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
brunogsa committed Jul 31, 2019
1 parent 69c7afb commit ceaf583
Show file tree
Hide file tree
Showing 14 changed files with 2,242 additions and 127 deletions.
1,828 changes: 1,771 additions & 57 deletions backend/package-lock.json

Large diffs are not rendered by default.

11 changes: 8 additions & 3 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"start": "nodemon -e js,json,graphql server.js",
"lint:graphql": "node .graphql-schema-validator.js && echo 'Valid GraphQL schema!'",
"test:graphql": "echo TODO"
"test:graphql": "mocha --exit tests/graphql.js"
},
"repository": {
"type": "git",
Expand All @@ -26,9 +26,14 @@
"dependencies": {
"express": "^4.17.1",
"express-graphql": "^0.9.0",
"graphql": "^14.4.2"
"graphql": "^14.4.2",
"graphql-scalars": "^0.4.6",
"graphql-tools": "^4.0.5"
},
"devDependencies": {
"nodemon": "^1.19.1"
"chai": "^4.2.0",
"mocha": "^6.2.0",
"nodemon": "^1.19.1",
"supertest": "^4.0.2"
}
}
55 changes: 22 additions & 33 deletions backend/resolvers/candidate.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,30 @@
const candidatesData = require('../data-sources/candidates.json');
const {
getAllCandidates,
getCandidateById,
getCandidateByEmail,
} = require('../services/candidates');

const getCandidateById = (id) => {
const candidate = candidatesData[id];
if (!candidate) return null;

candidate.id = id;
return candidate;
};

const getCandidateByEmail = (email) => {
const candidates = Object.keys(candidatesData).map(key => {
const candidate = candidatesData[key];

return {
id: key,
...candidate,
};
});
const resolver = {
Query: {
candidates: () => getAllCandidates(),

return candidates.find(
candidate => candidate.email === email,
);
};
candidate: (_, params, req, advancedDetails) => {
const { id, email } = params;

const resolver = {
candidate: ({ id, email }) => {
if (id) return getCandidateById(id);
if (email) return getCandidateByEmail(email);
throw new Error('Specify either an "id" or the "email"');
if (id) return getCandidateById(id);
if (email) return getCandidateByEmail(email);
throw new Error('Specify either an "id" or the "email"');
},
},

Candidate_id: (candidate) => candidate.id,
Candidate_name: (candidate) => candidate.name,
Candidate_email: (candidate) => candidate.email,
Candidate_profession: (candidate) => candidate.profession,
Candidate_photo: (candidate) => candidate.photo,
Candidate_following: (candidate) => candidate.following,
Candidate: {
id: (candidate) => candidate.id,
name: (candidate) => candidate.name,
email: (candidate) => candidate.email,
profession: (candidate) => candidate.profession,
photo: (candidate) => candidate.photo,
following: (candidate) => candidate.following.map(getCandidateById),
},
};

module.exports = resolver;
23 changes: 21 additions & 2 deletions backend/resolvers/company.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
const companiesData = require('../data-sources/companies.json');
const {
getAllCompanies,
getCompanyById,
} = require('../services/companies');

const { getJobAdById } = require('../services/jobAds');

const resolver = {
company: () => 'TODO',
Query: {
companies: () => getAllCompanies(),

company: (_, params, req, advancedDetails) => {
const { id } = params;
return getCompanyById(id);
},
},

Company: {
id: (company) => company.id,
name: (company) => company.name,
photo: (company) => company.photo,
openJobAds: (company) => company.openJobAds.map(getJobAdById),
},
};

module.exports = resolver;
9 changes: 9 additions & 0 deletions backend/resolvers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const fs = require('fs');

let resolvers = {};
let queryResolvers = {};

fs.readdirSync('./resolvers')
.filter(
Expand All @@ -13,7 +14,15 @@ fs.readdirSync('./resolvers')
...resolvers,
...fileResolvers,
};

if (!fileResolvers.Query) return;

queryResolvers = {
...queryResolvers,
...fileResolvers.Query,
};
});

resolvers.Query = queryResolvers;

module.exports = resolvers;
25 changes: 23 additions & 2 deletions backend/resolvers/jobAd.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
const jobAdsData = require('../data-sources/job-ads.json');
const {
getAllJobAds,
getJobAdById,
} = require('../services/jobAds');

const { getCompanyById } = require('../services/companies');

const resolver = {
jobAd: () => 'TODO',
Query: {
jobAds: () => getAllJobAds(),

jobAd: (_, params, req, advancedDetails) => {
const { id } = params;
return getJobAdById(id);
},
},

JobAd: {
id: (jobAd) => jobAd.id,
title: (jobAd) => jobAd.title,
description: (jobAd) => jobAd.description,
forCompany: (jobAd) => getCompanyById(jobAd.forCompany),
requiredProfession: (jobAd) => jobAd.requiredProfession,
remainingVacancies: (jobAd) => jobAd.remainingVacancies,
},
};

module.exports = resolver;
4 changes: 3 additions & 1 deletion backend/resolvers/ping.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const resolver = {
ping: () => 'pong',
Query: {
ping: () => 'pong',
},
};

module.exports = resolver;
26 changes: 9 additions & 17 deletions backend/resolvers/scalars.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
/**
* @see: https://graphql.org/graphql-js/type/#graphqlschema
* @see: https://github.com/Urigo/graphql-scalars
*/
const { GraphQLScalarType } = require('graphql');
const {
EmailAddress,
URL,
NonNegativeInt,
} = require('graphql-scalars');

const resolver = {
Email: new GraphQLScalarType({
name: 'Email',
description: 'An email address',

serialize: (value) => value,

parseValue: (value) => {
const isValid = value.match(/[a-zA-Z0-9._]@[a-z][.]com/g);
if (!isValid) throw new Error('Invalid email format');

return value;
},

parseLiteral: (ast) => ast.value,
}),
EmailAddress,
URL,
NonNegativeInt,
};

module.exports = resolver;
32 changes: 22 additions & 10 deletions backend/schema.graphql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
scalar Email
scalar EmailAddress
scalar URL
scalar PositiveInt
scalar NonNegativeInt

enum Profession {
FRONTEND
Expand All @@ -14,35 +14,47 @@ enum Profession {
type Candidate {
id: ID!
name: String!
email: Email!
email: EmailAddress!
profession: Profession!
photo: URL!
following: [ID!]!
following: [Candidate!]!
}

type Company {
id: ID!
name: String!
photo: URL!
openJobAds: [ID!]!
openJobAds: [JobAd!]!
}

type JobAd {
id: ID!
title: String!
description: String
forCompany: ID!
forCompany: Company!
requiredProfession: Profession!
remainingVacancies: PositiveInt
remainingVacancies: NonNegativeInt!
}

type Query {
"""Returns an incredible expected response"""
ping: String!

"""Get all candidates"""
candidates: [Candidate!]!

"""Get a candidate by either `id` or `email`"""
candidate(id: ID, email: Email): Candidate
candidate(id: ID, email: EmailAddress): Candidate

"""Get all companies"""
companies: [Company!]!

"""Get a specific company"""
company(id: ID!): Company

"""Get all job ads"""
jobAds: [JobAd!]!

# TODO: company query
# TODO: jobAd query
"""Get a specific job ad"""
jobAd(id: ID!): JobAd
}
10 changes: 8 additions & 2 deletions backend/server.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
const fs = require('fs');
const express = require('express');
const app = express();
const { graphql, buildSchema } = require('graphql');
const { makeExecutableSchema } = require('graphql-tools');
const graphqlHttp = require('express-graphql');

const PORT = 3000;
const graphqlTypes = fs.readFileSync('./schema.graphql', 'utf8');
const graphqlSchema = buildSchema(graphqlTypes);
const resolvers = require('./resolvers');

const graphqlSchema = makeExecutableSchema({
typeDefs: graphqlTypes,
resolvers,
});

app.get('/ping', (req, res) => {
return res.status(200).json({ message: 'pong' });
});
Expand All @@ -22,3 +26,5 @@ app.use('/graphql', graphqlHttp({
app.listen(PORT, () => {
console.log(`Server ready at http://localhost:${PORT}/graphql 🚀`);
});

module.exports = app;
36 changes: 36 additions & 0 deletions backend/services/candidates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const candidatesData = require('../data-sources/candidates.json');

const getAllCandidates = () => {
const candidates = Object.keys(candidatesData).map(key => {
const candidate = candidatesData[key];

return {
id: key,
...candidate,
};
});

return candidates;
};

const getCandidateById = (id) => {
const candidate = candidatesData[id];
if (!candidate) return null;

candidate.id = id;
return candidate;
};

const getCandidateByEmail = (email) => {
const candidates = getAllCandidates();

return candidates.find(
candidate => candidate.email === email,
);
};

module.exports = {
getAllCandidates,
getCandidateById,
getCandidateByEmail,
};
16 changes: 16 additions & 0 deletions backend/services/companies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const companiesData = require('../data-sources/companies.json');

const getAllCompanies = () => {
return companiesData;
};

const getCompanyById = (id) => {
return companiesData.find(
company => company.id == id,
);
};

module.exports = {
getAllCompanies,
getCompanyById,
};
27 changes: 27 additions & 0 deletions backend/services/jobAds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const jobAdsData = require('../data-sources/job-ads.json');

const getAllJobAds = () => {
const jobAds = Object.keys(jobAdsData).map(key => {
const jobAd = jobAdsData[key];

return {
id: key,
...jobAd,
};
});

return jobAds;
};

const getJobAdById = (id) => {
const jobAd = jobAdsData[id];
if (!jobAd) return null;

jobAd.id = id;
return jobAd;
};

module.exports = {
getAllJobAds,
getJobAdById,
};
Loading

0 comments on commit ceaf583

Please sign in to comment.