mirror of
https://github.com/FranP-code/countries.git
synced 2025-10-13 00:02:15 +00:00
Move schema to its own file
This commit is contained in:
187
index.js
187
index.js
@@ -1,192 +1,11 @@
|
|||||||
const sift = require('sift');
|
import {ApolloServer} from 'apollo-server';
|
||||||
const provinces = require('provinces');
|
import {resolvers, typeDefs} from './schema.js';
|
||||||
const {ApolloServer, gql} = require('apollo-server');
|
|
||||||
const {continents, countries, languages} = require('countries-list');
|
|
||||||
|
|
||||||
const typeDefs = gql`
|
|
||||||
type Continent {
|
|
||||||
code: ID!
|
|
||||||
name: String!
|
|
||||||
countries: [Country!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Country {
|
|
||||||
code: ID!
|
|
||||||
name: String!
|
|
||||||
native: String!
|
|
||||||
phone: String!
|
|
||||||
continent: Continent!
|
|
||||||
capital: String
|
|
||||||
currency: String
|
|
||||||
languages: [Language!]!
|
|
||||||
emoji: String!
|
|
||||||
emojiU: String!
|
|
||||||
states: [State!]!
|
|
||||||
}
|
|
||||||
|
|
||||||
type State {
|
|
||||||
code: String
|
|
||||||
name: String!
|
|
||||||
country: Country!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Language {
|
|
||||||
code: ID!
|
|
||||||
name: String
|
|
||||||
native: String
|
|
||||||
rtl: Boolean!
|
|
||||||
}
|
|
||||||
|
|
||||||
input StringQueryOperatorInput {
|
|
||||||
eq: String
|
|
||||||
ne: String
|
|
||||||
in: [String]
|
|
||||||
nin: [String]
|
|
||||||
regex: String
|
|
||||||
glob: String
|
|
||||||
}
|
|
||||||
|
|
||||||
input CountryFilterInput {
|
|
||||||
code: StringQueryOperatorInput
|
|
||||||
currency: StringQueryOperatorInput
|
|
||||||
continent: StringQueryOperatorInput
|
|
||||||
}
|
|
||||||
|
|
||||||
input ContinentFilterInput {
|
|
||||||
code: StringQueryOperatorInput
|
|
||||||
}
|
|
||||||
|
|
||||||
input LanguageFilterInput {
|
|
||||||
code: StringQueryOperatorInput
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
|
||||||
continents(filter: ContinentFilterInput): [Continent!]!
|
|
||||||
continent(code: ID!): Continent
|
|
||||||
countries(filter: CountryFilterInput): [Country!]!
|
|
||||||
country(code: ID!): Country
|
|
||||||
languages(filter: LanguageFilterInput): [Language!]!
|
|
||||||
language(code: ID!): Language
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
function filterToSift(filter = {}) {
|
|
||||||
return sift(
|
|
||||||
Object.entries(filter).reduce(
|
|
||||||
(acc, [key, operators]) => ({
|
|
||||||
...acc,
|
|
||||||
[key]: operatorsToSift(operators)
|
|
||||||
}),
|
|
||||||
{}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function operatorsToSift(operators) {
|
|
||||||
return Object.entries(operators).reduce(
|
|
||||||
(acc, [operator, value]) => ({
|
|
||||||
...acc,
|
|
||||||
['$' + operator]: value
|
|
||||||
}),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolvers = {
|
|
||||||
Country: {
|
|
||||||
capital: country => country.capital || null,
|
|
||||||
currency: country => country.currency || null,
|
|
||||||
continent: ({continent}) => ({
|
|
||||||
code: continent,
|
|
||||||
name: continents[continent]
|
|
||||||
}),
|
|
||||||
languages: country =>
|
|
||||||
country.languages.map(code => {
|
|
||||||
const language = languages[code];
|
|
||||||
return {
|
|
||||||
...language,
|
|
||||||
code
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
states: country =>
|
|
||||||
provinces.filter(province => province.country === country.code)
|
|
||||||
},
|
|
||||||
State: {
|
|
||||||
code: state => state.short,
|
|
||||||
country: state => countries[state.country]
|
|
||||||
},
|
|
||||||
Continent: {
|
|
||||||
countries: continent =>
|
|
||||||
Object.entries(countries)
|
|
||||||
.filter(entry => entry[1].continent === continent.code)
|
|
||||||
.map(([code, country]) => ({
|
|
||||||
...country,
|
|
||||||
code
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
Language: {
|
|
||||||
rtl: language => Boolean(language.rtl)
|
|
||||||
},
|
|
||||||
Query: {
|
|
||||||
continent(parent, {code}) {
|
|
||||||
const name = continents[code];
|
|
||||||
return (
|
|
||||||
name && {
|
|
||||||
code,
|
|
||||||
name
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
continents: (parent, {filter}) =>
|
|
||||||
Object.entries(continents)
|
|
||||||
.map(([code, name]) => ({
|
|
||||||
code,
|
|
||||||
name
|
|
||||||
}))
|
|
||||||
.filter(filterToSift(filter)),
|
|
||||||
country(parent, {code}) {
|
|
||||||
const country = countries[code];
|
|
||||||
return (
|
|
||||||
country && {
|
|
||||||
...country,
|
|
||||||
code
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
countries: (parent, {filter}) =>
|
|
||||||
Object.entries(countries)
|
|
||||||
.map(([code, country]) => ({
|
|
||||||
...country,
|
|
||||||
code
|
|
||||||
}))
|
|
||||||
.filter(filterToSift(filter)),
|
|
||||||
language(parent, {code}) {
|
|
||||||
const language = languages[code];
|
|
||||||
return (
|
|
||||||
language && {
|
|
||||||
...language,
|
|
||||||
code
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
languages: (parent, {filter}) =>
|
|
||||||
Object.entries(languages)
|
|
||||||
.map(([code, language]) => ({
|
|
||||||
...language,
|
|
||||||
code
|
|
||||||
}))
|
|
||||||
.filter(filterToSift(filter))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const server = new ApolloServer({
|
const server = new ApolloServer({
|
||||||
typeDefs,
|
typeDefs,
|
||||||
resolvers,
|
resolvers,
|
||||||
introspection: true,
|
introspection: true,
|
||||||
playground: true,
|
playground: true
|
||||||
engine: {
|
|
||||||
apiKey: process.env.ENGINE_API_KEY
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen({port: process.env.PORT || 4000}).then(({url}) => {
|
server.listen({port: process.env.PORT || 4000}).then(({url}) => {
|
||||||
|
|||||||
3810
package-lock.json
generated
3810
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,12 @@
|
|||||||
"pretest": "eslint index.js",
|
"pretest": "eslint index.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit"
|
"test": "echo \"Error: no test specified\" && exit"
|
||||||
},
|
},
|
||||||
|
"type": "module",
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "@trevorblades"
|
"extends": "@trevorblades"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"apollo-server": "^2.14.2",
|
"apollo-server": "^2.25.3",
|
||||||
"countries-list": "^2.5.4",
|
"countries-list": "^2.5.4",
|
||||||
"graphql": "^14.6.0",
|
"graphql": "^14.6.0",
|
||||||
"provinces": "^1.11.0",
|
"provinces": "^1.11.0",
|
||||||
|
|||||||
182
schema.js
Normal file
182
schema.js
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
import countriesList from 'countries-list';
|
||||||
|
import provinces from 'provinces';
|
||||||
|
import sift from 'sift';
|
||||||
|
import {gql} from 'apollo-server';
|
||||||
|
|
||||||
|
export const typeDefs = gql`
|
||||||
|
type Continent {
|
||||||
|
code: ID!
|
||||||
|
name: String!
|
||||||
|
countries: [Country!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Country {
|
||||||
|
code: ID!
|
||||||
|
name: String!
|
||||||
|
native: String!
|
||||||
|
phone: String!
|
||||||
|
continent: Continent!
|
||||||
|
capital: String
|
||||||
|
currency: String
|
||||||
|
languages: [Language!]!
|
||||||
|
emoji: String!
|
||||||
|
emojiU: String!
|
||||||
|
states: [State!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type State {
|
||||||
|
code: String
|
||||||
|
name: String!
|
||||||
|
country: Country!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Language {
|
||||||
|
code: ID!
|
||||||
|
name: String
|
||||||
|
native: String
|
||||||
|
rtl: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
input StringQueryOperatorInput {
|
||||||
|
eq: String
|
||||||
|
ne: String
|
||||||
|
in: [String]
|
||||||
|
nin: [String]
|
||||||
|
regex: String
|
||||||
|
glob: String
|
||||||
|
}
|
||||||
|
|
||||||
|
input CountryFilterInput {
|
||||||
|
code: StringQueryOperatorInput
|
||||||
|
currency: StringQueryOperatorInput
|
||||||
|
continent: StringQueryOperatorInput
|
||||||
|
}
|
||||||
|
|
||||||
|
input ContinentFilterInput {
|
||||||
|
code: StringQueryOperatorInput
|
||||||
|
}
|
||||||
|
|
||||||
|
input LanguageFilterInput {
|
||||||
|
code: StringQueryOperatorInput
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
continents(filter: ContinentFilterInput): [Continent!]!
|
||||||
|
continent(code: ID!): Continent
|
||||||
|
countries(filter: CountryFilterInput): [Country!]!
|
||||||
|
country(code: ID!): Country
|
||||||
|
languages(filter: LanguageFilterInput): [Language!]!
|
||||||
|
language(code: ID!): Language
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
function filterToSift(filter = {}) {
|
||||||
|
return sift(
|
||||||
|
Object.entries(filter).reduce(
|
||||||
|
(acc, [key, operators]) => ({
|
||||||
|
...acc,
|
||||||
|
[key]: operatorsToSift(operators)
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function operatorsToSift(operators) {
|
||||||
|
return Object.entries(operators).reduce(
|
||||||
|
(acc, [operator, value]) => ({
|
||||||
|
...acc,
|
||||||
|
['$' + operator]: value
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const {continents, countries, languages} = countriesList;
|
||||||
|
|
||||||
|
export const resolvers = {
|
||||||
|
Country: {
|
||||||
|
capital: country => country.capital || null,
|
||||||
|
currency: country => country.currency || null,
|
||||||
|
continent: ({continent}) => ({
|
||||||
|
code: continent,
|
||||||
|
name: continents[continent]
|
||||||
|
}),
|
||||||
|
languages: country =>
|
||||||
|
country.languages.map(code => {
|
||||||
|
const language = languages[code];
|
||||||
|
return {
|
||||||
|
...language,
|
||||||
|
code
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
states: country =>
|
||||||
|
provinces.filter(province => province.country === country.code)
|
||||||
|
},
|
||||||
|
State: {
|
||||||
|
code: state => state.short,
|
||||||
|
country: state => countries[state.country]
|
||||||
|
},
|
||||||
|
Continent: {
|
||||||
|
countries: continent =>
|
||||||
|
Object.entries(countries)
|
||||||
|
.filter(entry => entry[1].continent === continent.code)
|
||||||
|
.map(([code, country]) => ({
|
||||||
|
...country,
|
||||||
|
code
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
Language: {
|
||||||
|
rtl: language => Boolean(language.rtl)
|
||||||
|
},
|
||||||
|
Query: {
|
||||||
|
continent(parent, {code}) {
|
||||||
|
const name = continents[code];
|
||||||
|
return (
|
||||||
|
name && {
|
||||||
|
code,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
continents: (parent, {filter}) =>
|
||||||
|
Object.entries(continents)
|
||||||
|
.map(([code, name]) => ({
|
||||||
|
code,
|
||||||
|
name
|
||||||
|
}))
|
||||||
|
.filter(filterToSift(filter)),
|
||||||
|
country(parent, {code}) {
|
||||||
|
const country = countries[code];
|
||||||
|
return (
|
||||||
|
country && {
|
||||||
|
...country,
|
||||||
|
code
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
countries: (parent, {filter}) =>
|
||||||
|
Object.entries(countries)
|
||||||
|
.map(([code, country]) => ({
|
||||||
|
...country,
|
||||||
|
code
|
||||||
|
}))
|
||||||
|
.filter(filterToSift(filter)),
|
||||||
|
language(parent, {code}) {
|
||||||
|
const language = languages[code];
|
||||||
|
return (
|
||||||
|
language && {
|
||||||
|
...language,
|
||||||
|
code
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
languages: (parent, {filter}) =>
|
||||||
|
Object.entries(languages)
|
||||||
|
.map(([code, language]) => ({
|
||||||
|
...language,
|
||||||
|
code
|
||||||
|
}))
|
||||||
|
.filter(filterToSift(filter))
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user