diff --git a/graphql/index.ts b/graphql/index.ts index fe49612..b387269 100644 --- a/graphql/index.ts +++ b/graphql/index.ts @@ -1,56 +1,28 @@ import express from 'express' import { ApolloServer, Config } from 'apollo-server-express' -import responseCachePlugin from 'apollo-server-plugin-response-cache' +import { ApolloServerPluginCacheControl } from 'apollo-server-core' import { typeDefs, resolvers } from './schema' -const defaultQuery = `{ - commits - tweets - places - steps - songs - album { - name - artist - } - books { - name - author - } -}` +async function startApolloServer() { + const app = express() -// Set up Express -const app = express() + const config: Config = { + typeDefs, + resolvers, + plugins: [ApolloServerPluginCacheControl()], + introspection: true, + } -const config: Config = { - typeDefs, - resolvers, - cacheControl: true, - tracing: true, - introspection: true, - playground: true, -} - -if (process.env.NODE_ENV === 'production') { - config.playground = { - tabs: [ - { - endpoint: 'https://stats.lowmess.com/graphql', - query: defaultQuery, - }, - ], - } + const server = new ApolloServer(config) - config.plugins = [responseCachePlugin()] -} + await server.start() -const server = new ApolloServer(config) + server.applyMiddleware({ + app, + cors: { origin: [/lowmess/, /localhost/] }, + }) -server.applyMiddleware({ - app, - cors: { origin: [/lowmess/, /localhost/] }, -}) - -app.listen() + app.listen() +} -export default app +startApolloServer() diff --git a/graphql/schema.ts b/graphql/schema.ts index e127141..4a27d50 100755 --- a/graphql/schema.ts +++ b/graphql/schema.ts @@ -1,5 +1,4 @@ /* eslint-disable no-shadow */ - import { gql } from 'apollo-server-express' import logError from './lib/logError' import getCommits from './resolvers/commits' @@ -12,100 +11,111 @@ import getBooks, { Book } from './resolvers/books' // Construct a schema, using GraphQL schema language const typeDefs = gql` - type Album { - name: String - artist: String - } + enum CacheControlScope { + PUBLIC + PRIVATE + } + + directive @cacheControl( + maxAge: Int + scope: CacheControlScope + inheritMaxAge: Boolean + ) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION + + type Album { + name: String + artist: String + } - type Book { - name: String - author: String - } + type Book { + name: String + author: String + } - type Query { - commits: Int @cacheControl(maxAge: 3600) - tweets: Int @cacheControl(maxAge: 3600) - places: Int @cacheControl(maxAge: 21600) - steps: Int @cacheControl(maxAge: 3600) - songs: Int @cacheControl(maxAge: 3600) - album: Album @cacheControl(maxAge: 3600) - books: [Book] @cacheControl(maxAge: 86400) - } + type Query { + commits: Int @cacheControl(maxAge: 3600) + tweets: Int @cacheControl(maxAge: 3600) + places: Int @cacheControl(maxAge: 21600) + steps: Int @cacheControl(maxAge: 3600) + songs: Int @cacheControl(maxAge: 3600) + album: Album @cacheControl(maxAge: 3600) + books: [Book] @cacheControl(maxAge: 86400) + } ` // Provide resolver functions for your schema fields const resolvers = { - Query: { - // GitHub Commits - commits: async (): Promise => { - try { - const commits = await getCommits() - return commits - } catch (error) { - logError('Commits resolver error', error.message) - return null - } - }, - // Tweets - tweets: async (): Promise => { - try { - const tweets = await getTweets() - return tweets - } catch (error) { - logError('Tweets resolver error', error.message) - return null - } - }, - // Foursquare places - places: async (): Promise => { - try { - const places = await getPlaces() - return places - } catch (error) { - logError('Places resolver error', error.message) - return null - } - }, - // FitBit steps & hours slept - steps: async (): Promise => { - try { - const steps = await getSteps() - return steps - } catch (error) { - logError('Steps resolver error', error.message) - return null - } - }, - // Last.fm top album & total songs - songs: async (): Promise => { - try { - const songs = await getSongs() - return songs - } catch (error) { - logError('Songs resolver error', error.message) - return null - } - }, - album: async (): Promise => { - try { - const album = await getAlbum() - return album - } catch (error) { - logError('Album resolver error', error.message) - return null - } - }, - // Goodreads book - books: async (): Promise => { - try { - const books = await getBooks() - return books - } catch (error) { - logError('Books resolver error', error.message) - return null - } - }, - }, + Query: { + // GitHub Commits + commits: async (): Promise => { + try { + const commits = await getCommits() + return commits + } catch (error) { + logError('Commits resolver error', error.message) + return null + } + }, + // Tweets + tweets: async (): Promise => { + try { + const tweets = await getTweets() + return tweets + } catch (error) { + logError('Tweets resolver error', error.message) + return null + } + }, + // Foursquare places + places: async (): Promise => { + try { + const places = await getPlaces() + return places + } catch (error) { + logError('Places resolver error', error.message) + return null + } + }, + // FitBit steps & hours slept + steps: async (): Promise => { + try { + const steps = await getSteps() + return steps + } catch (error) { + logError('Steps resolver error', error.message) + return null + } + }, + // Last.fm top album & total songs + songs: async (): Promise => { + try { + const songs = await getSongs() + return songs + } catch (error) { + logError('Songs resolver error', error.message) + return null + } + }, + album: async (): Promise => { + try { + const album = await getAlbum() + return album + } catch (error) { + logError('Album resolver error', error.message) + return null + } + }, + // Goodreads book + books: async (): Promise => { + try { + const books = await getBooks() + return books + } catch (error) { + logError('Books resolver error', error.message) + return null + } + }, + }, } export { typeDefs, resolvers }