diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/datasources/senpy.js | 27 | ||||
| -rw-r--r-- | src/handlers/apollo.js | 36 | ||||
| -rw-r--r-- | src/handlers/playground.js | 498 | ||||
| -rw-r--r-- | src/index.js | 56 | ||||
| -rw-r--r-- | src/kv-cache.js | 16 | ||||
| -rw-r--r-- | src/resolvers.js | 13 | ||||
| -rw-r--r-- | src/schema.js | 14 | ||||
| -rw-r--r-- | src/utils/setCors.js | 23 |
8 files changed, 683 insertions, 0 deletions
diff --git a/src/datasources/senpy.js b/src/datasources/senpy.js new file mode 100644 index 0000000..1d9ba2a --- /dev/null +++ b/src/datasources/senpy.js @@ -0,0 +1,27 @@ +const { RESTDataSource } = require("apollo-datasource-rest"); + +module.exports = class SenpyAPI extends RESTDataSource { + constructor() { + super(); + + /** + * We have to use the <workers.dev> domain instead of the custom domain + * because worker intercommunication still isn't a thing... + * + * Tracking: <https://community.cloudflare.com/t/issue-with-worker-to-worker-https-request/94472> + */ + this.baseURL = "https://senpy-club-api-worker.fuwn.workers.dev/v2/"; + } + + async getRandom() { + return this.get("random"); + } + + async getLanguages() { + return this.get("languages"); + } + + async getLanguage(language) { + return this.get(`language/${language}`); + } +}; diff --git a/src/handlers/apollo.js b/src/handlers/apollo.js new file mode 100644 index 0000000..45746e0 --- /dev/null +++ b/src/handlers/apollo.js @@ -0,0 +1,36 @@ +const { ApolloServer } = require("apollo-server-cloudflare"); +const { + graphqlCloudflare, +} = require("apollo-server-cloudflare/dist/cloudflareApollo"); + +const KVCache = require("../kv-cache"); +const SenpyAPI = require("../datasources/senpy"); +const resolvers = require("../resolvers"); +const typeDefs = require("../schema"); + +const dataSources = () => ({ + senpyAPI: new SenpyAPI(), +}); + +const kvCache = { cache: new KVCache() }; + +const createServer = (graphQLOptions) => + new ApolloServer({ + typeDefs, + resolvers, + introspection: true, + dataSources, + ...(graphQLOptions.kvCache ? kvCache : {}), + }); + +const handler = async (request, graphQLOptions) => { + const server = createServer(graphQLOptions); + + await server.start(); + + return graphqlCloudflare(() => server.createGraphQLServerOptions(request))( + request + ); +}; + +module.exports = handler; diff --git a/src/handlers/playground.js b/src/handlers/playground.js new file mode 100644 index 0000000..636b369 --- /dev/null +++ b/src/handlers/playground.js @@ -0,0 +1,498 @@ +const html = (baseEndpoint) => ` +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset=utf-8 /> + <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui"> + <title>GraphQL Playground</title> + <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/graphql-playground-react/build/static/css/index.css" /> + <link rel="shortcut icon" href="//cdn.jsdelivr.net/npm/graphql-playground-react/build/favicon.png" /> + <script src="//cdn.jsdelivr.net/npm/graphql-playground-react/build/static/js/middleware.js"></script> + </head> + + <body> + <style type="text/css"> + html { + font-family: "Open Sans", sans-serif; + overflow: hidden; + } + body { + margin: 0; + background: #172a3a; + } + .playgroundIn { + -webkit-animation: playgroundIn 0.5s ease-out forwards; + animation: playgroundIn 0.5s ease-out forwards; + } + @-webkit-keyframes playgroundIn { + from { + opacity: 0; + -webkit-transform: translateY(10px); + -ms-transform: translateY(10px); + transform: translateY(10px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + @keyframes playgroundIn { + from { + opacity: 0; + -webkit-transform: translateY(10px); + -ms-transform: translateY(10px); + transform: translateY(10px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + </style> + + <style type="text/css"> + .fadeOut { + -webkit-animation: fadeOut 0.5s ease-out forwards; + animation: fadeOut 0.5s ease-out forwards; + } + @-webkit-keyframes fadeIn { + from { + opacity: 0; + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + @keyframes fadeIn { + from { + opacity: 0; + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + @-webkit-keyframes fadeOut { + from { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + to { + opacity: 0; + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + } + @keyframes fadeOut { + from { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + to { + opacity: 0; + -webkit-transform: translateY(-10px); + -ms-transform: translateY(-10px); + transform: translateY(-10px); + } + } + @-webkit-keyframes appearIn { + from { + opacity: 0; + -webkit-transform: translateY(0px); + -ms-transform: translateY(0px); + transform: translateY(0px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + @keyframes appearIn { + from { + opacity: 0; + -webkit-transform: translateY(0px); + -ms-transform: translateY(0px); + transform: translateY(0px); + } + to { + opacity: 1; + -webkit-transform: translateY(0); + -ms-transform: translateY(0); + transform: translateY(0); + } + } + @-webkit-keyframes scaleIn { + from { + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + } + to { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + } + @keyframes scaleIn { + from { + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + } + to { + -webkit-transform: scale(1); + -ms-transform: scale(1); + transform: scale(1); + } + } + @-webkit-keyframes innerDrawIn { + 0% { + stroke-dashoffset: 70; + } + 50% { + stroke-dashoffset: 140; + } + 100% { + stroke-dashoffset: 210; + } + } + @keyframes innerDrawIn { + 0% { + stroke-dashoffset: 70; + } + 50% { + stroke-dashoffset: 140; + } + 100% { + stroke-dashoffset: 210; + } + } + @-webkit-keyframes outerDrawIn { + 0% { + stroke-dashoffset: 76; + } + 100% { + stroke-dashoffset: 152; + } + } + @keyframes outerDrawIn { + 0% { + stroke-dashoffset: 76; + } + 100% { + stroke-dashoffset: 152; + } + } + .hHWjkv { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.2222222222222222s; + animation: scaleIn 0.25s linear forwards 0.2222222222222222s; + } + .gCDOzd { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.4222222222222222s; + animation: scaleIn 0.25s linear forwards 0.4222222222222222s; + } + .hmCcxi { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.6222222222222222s; + animation: scaleIn 0.25s linear forwards 0.6222222222222222s; + } + .eHamQi { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.8222222222222223s; + animation: scaleIn 0.25s linear forwards 0.8222222222222223s; + } + .byhgGu { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 1.0222222222222221s; + animation: scaleIn 0.25s linear forwards 1.0222222222222221s; + } + .llAKP { + -webkit-transform-origin: 0px 0px; + -ms-transform-origin: 0px 0px; + transform-origin: 0px 0px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 1.2222222222222223s; + animation: scaleIn 0.25s linear forwards 1.2222222222222223s; + } + .bglIGM { + -webkit-transform-origin: 64px 28px; + -ms-transform-origin: 64px 28px; + transform-origin: 64px 28px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.2222222222222222s; + animation: scaleIn 0.25s linear forwards 0.2222222222222222s; + } + .ksxRII { + -webkit-transform-origin: 95.98500061035156px 46.510000228881836px; + -ms-transform-origin: 95.98500061035156px 46.510000228881836px; + transform-origin: 95.98500061035156px 46.510000228881836px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.4222222222222222s; + animation: scaleIn 0.25s linear forwards 0.4222222222222222s; + } + .cWrBmb { + -webkit-transform-origin: 95.97162628173828px 83.4900016784668px; + -ms-transform-origin: 95.97162628173828px 83.4900016784668px; + transform-origin: 95.97162628173828px 83.4900016784668px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.6222222222222222s; + animation: scaleIn 0.25s linear forwards 0.6222222222222222s; + } + .Wnusb { + -webkit-transform-origin: 64px 101.97999572753906px; + -ms-transform-origin: 64px 101.97999572753906px; + transform-origin: 64px 101.97999572753906px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 0.8222222222222223s; + animation: scaleIn 0.25s linear forwards 0.8222222222222223s; + } + .bfPqf { + -webkit-transform-origin: 32.03982162475586px 83.4900016784668px; + -ms-transform-origin: 32.03982162475586px 83.4900016784668px; + transform-origin: 32.03982162475586px 83.4900016784668px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 1.0222222222222221s; + animation: scaleIn 0.25s linear forwards 1.0222222222222221s; + } + .edRCTN { + -webkit-transform-origin: 32.033552169799805px 46.510000228881836px; + -ms-transform-origin: 32.033552169799805px 46.510000228881836px; + transform-origin: 32.033552169799805px 46.510000228881836px; + -webkit-transform: scale(0); + -ms-transform: scale(0); + transform: scale(0); + -webkit-animation: scaleIn 0.25s linear forwards 1.2222222222222223s; + animation: scaleIn 0.25s linear forwards 1.2222222222222223s; + } + .iEGVWn { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 0.3333333333333333s, appearIn 0.1s ease-out forwards 0.3333333333333333s; + animation: outerDrawIn 0.5s ease-out forwards 0.3333333333333333s, appearIn 0.1s ease-out forwards 0.3333333333333333s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .bsocdx { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 0.5333333333333333s, appearIn 0.1s ease-out forwards 0.5333333333333333s; + animation: outerDrawIn 0.5s ease-out forwards 0.5333333333333333s, appearIn 0.1s ease-out forwards 0.5333333333333333s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .jAZXmP { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 0.7333333333333334s, appearIn 0.1s ease-out forwards 0.7333333333333334s; + animation: outerDrawIn 0.5s ease-out forwards 0.7333333333333334s, appearIn 0.1s ease-out forwards 0.7333333333333334s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .hSeArx { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 0.9333333333333333s, appearIn 0.1s ease-out forwards 0.9333333333333333s; + animation: outerDrawIn 0.5s ease-out forwards 0.9333333333333333s, appearIn 0.1s ease-out forwards 0.9333333333333333s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .bVgqGk { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 1.1333333333333333s, appearIn 0.1s ease-out forwards 1.1333333333333333s; + animation: outerDrawIn 0.5s ease-out forwards 1.1333333333333333s, appearIn 0.1s ease-out forwards 1.1333333333333333s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .hEFqBt { + opacity: 0; + stroke-dasharray: 76; + -webkit-animation: outerDrawIn 0.5s ease-out forwards 1.3333333333333333s, appearIn 0.1s ease-out forwards 1.3333333333333333s; + animation: outerDrawIn 0.5s ease-out forwards 1.3333333333333333s, appearIn 0.1s ease-out forwards 1.3333333333333333s; + -webkit-animation-iteration-count: 1, 1; + animation-iteration-count: 1, 1; + } + .dzEKCM { + opacity: 0; + stroke-dasharray: 70; + -webkit-animation: innerDrawIn 1s ease-in-out forwards 1.3666666666666667s, appearIn 0.1s linear forwards 1.3666666666666667s; + animation: innerDrawIn 1s ease-in-out forwards 1.3666666666666667s, appearIn 0.1s linear forwards 1.3666666666666667s; + -webkit-animation-iteration-count: infinite, 1; + animation-iteration-count: infinite, 1; + } + .DYnPx { + opacity: 0; + stroke-dasharray: 70; + -webkit-animation: innerDrawIn 1s ease-in-out forwards 1.5333333333333332s, appearIn 0.1s linear forwards 1.5333333333333332s; + animation: innerDrawIn 1s ease-in-out forwards 1.5333333333333332s, appearIn 0.1s linear forwards 1.5333333333333332s; + -webkit-animation-iteration-count: infinite, 1; + animation-iteration-count: infinite, 1; + } + .hjPEAQ { + opacity: 0; + stroke-dasharray: 70; + -webkit-animation: innerDrawIn 1s ease-in-out forwards 1.7000000000000002s, appearIn 0.1s linear forwards 1.7000000000000002s; + animation: innerDrawIn 1s ease-in-out forwards 1.7000000000000002s, appearIn 0.1s linear forwards 1.7000000000000002s; + -webkit-animation-iteration-count: infinite, 1; + animation-iteration-count: infinite, 1; + } + #loading-wrapper { + position: absolute; + width: 100vw; + height: 100vh; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + } + .logo { + width: 75px; + height: 75px; + margin-bottom: 20px; + opacity: 0; + -webkit-animation: fadeIn 0.5s ease-out forwards; + animation: fadeIn 0.5s ease-out forwards; + } + .text { + font-size: 32px; + font-weight: 200; + text-align: center; + color: rgba(255, 255, 255, 0.6); + opacity: 0; + -webkit-animation: fadeIn 0.5s ease-out forwards; + animation: fadeIn 0.5s ease-out forwards; + } + .dGfHfc { + font-weight: 400; + } + </style> + <div id="loading-wrapper"> + <svg class="logo" viewBox="0 0 128 128" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>GraphQL Playground Logo</title> + <defs> + <linearGradient id="linearGradient-1" x1="4.86%" x2="96.21%" y1="0%" y2="99.66%"> + <stop stop-color="#E00082" stop-opacity=".8" offset="0%"></stop> + <stop stop-color="#E00082" offset="100%"></stop> + </linearGradient> + </defs> + <g> + <rect id="Gradient" width="127.96" height="127.96" y="1" fill="url(#linearGradient-1)" rx="4"></rect> + <path id="Border" fill="#E00082" fill-rule="nonzero" d="M4.7 2.84c-1.58 0-2.86 1.28-2.86 2.85v116.57c0 1.57 1.28 2.84 2.85 2.84h116.57c1.57 0 2.84-1.26 2.84-2.83V5.67c0-1.55-1.26-2.83-2.83-2.83H4.67zM4.7 0h116.58c3.14 0 5.68 2.55 5.68 5.7v116.58c0 3.14-2.54 5.68-5.68 5.68H4.68c-3.13 0-5.68-2.54-5.68-5.68V5.68C-1 2.56 1.55 0 4.7 0z"></path> + <path class="bglIGM" x="64" y="28" fill="#fff" d="M64 36c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8" style="transform: translate(100px, 100px);"></path> + <path class="ksxRII" x="95.98500061035156" y="46.510000228881836" fill="#fff" d="M89.04 50.52c-2.2-3.84-.9-8.73 2.94-10.96 3.83-2.2 8.72-.9 10.95 2.94 2.2 3.84.9 8.73-2.94 10.96-3.85 2.2-8.76.9-10.97-2.94" + style="transform: translate(100px, 100px);"></path> + <path class="cWrBmb" x="95.97162628173828" y="83.4900016784668" fill="#fff" d="M102.9 87.5c-2.2 3.84-7.1 5.15-10.94 2.94-3.84-2.2-5.14-7.12-2.94-10.96 2.2-3.84 7.12-5.15 10.95-2.94 3.86 2.23 5.16 7.12 2.94 10.96" + style="transform: translate(100px, 100px);"></path> + <path class="Wnusb" x="64" y="101.97999572753906" fill="#fff" d="M64 110c-4.43 0-8-3.6-8-8.02 0-4.44 3.57-8.02 8-8.02s8 3.58 8 8.02c0 4.4-3.57 8.02-8 8.02" + style="transform: translate(100px, 100px);"></path> + <path class="bfPqf" x="32.03982162475586" y="83.4900016784668" fill="#fff" d="M25.1 87.5c-2.2-3.84-.9-8.73 2.93-10.96 3.83-2.2 8.72-.9 10.95 2.94 2.2 3.84.9 8.73-2.94 10.96-3.85 2.2-8.74.9-10.95-2.94" + style="transform: translate(100px, 100px);"></path> + <path class="edRCTN" x="32.033552169799805" y="46.510000228881836" fill="#fff" d="M38.96 50.52c-2.2 3.84-7.12 5.15-10.95 2.94-3.82-2.2-5.12-7.12-2.92-10.96 2.2-3.84 7.12-5.15 10.95-2.94 3.83 2.23 5.14 7.12 2.94 10.96" + style="transform: translate(100px, 100px);"></path> + <path class="iEGVWn" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M63.55 27.5l32.9 19-32.9-19z"></path> + <path class="bsocdx" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M96 46v38-38z"></path> + <path class="jAZXmP" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M96.45 84.5l-32.9 19 32.9-19z"></path> + <path class="hSeArx" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M64.45 103.5l-32.9-19 32.9 19z"></path> + <path class="bVgqGk" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M32 84V46v38z"></path> + <path class="hEFqBt" stroke="#fff" stroke-width="4" stroke-linecap="round" stroke-linejoin="round" d="M31.55 46.5l32.9-19-32.9 19z"></path> + <path class="dzEKCM" id="Triangle-Bottom" stroke="#fff" stroke-width="4" d="M30 84h70" stroke-linecap="round"></path> + <path class="DYnPx" id="Triangle-Left" stroke="#fff" stroke-width="4" d="M65 26L30 87" stroke-linecap="round"></path> + <path class="hjPEAQ" id="Triangle-Right" stroke="#fff" stroke-width="4" d="M98 87L63 26" stroke-linecap="round"></path> + </g> + </svg> + <div class="text">Loading + <span class="dGfHfc">GraphQL Playground</span> + </div> + </div> + + <div id="root" /> + <script type="text/javascript"> + window.addEventListener('load', function (event) { + const loadingWrapper = document.getElementById('loading-wrapper'); + loadingWrapper.classList.add('fadeOut'); + const root = document.getElementById('root'); + root.classList.add('playgroundIn'); + GraphQLPlayground.init(root, { endpoint: "${baseEndpoint}" }) + }) + </script> + </body> +</html> +`; + +const headers = { "Content-Type": "text/html" }; +const handler = (request, { baseEndpoint }) => + new Response(html(baseEndpoint), { headers }); + +module.exports = handler; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..7419cc8 --- /dev/null +++ b/src/index.js @@ -0,0 +1,56 @@ +const apollo = require("./handlers/apollo"); +const playground = require("./handlers/playground"); +const setCors = require("./utils/setCors"); + +const graphQLOptions = { + baseEndpoint: "/", + playgroundEndpoint: "/playground", + forwardUnmatchedRequestsToOrigin: false, + debug: false, + + // cors: { + // allowCredentials: 'true', + // allowHeaders: 'Content-type', + // allowOrigin: '*', + // allowMethods: 'GET, POST, PUT', + // }, + cors: true, + + kvCache: true, +}; + +const handleRequest = async (request) => { + const url = new URL(request.url); + + try { + if (url.pathname === graphQLOptions.baseEndpoint) { + const response = + request.method === "OPTIONS" + ? new Response("", { status: 204 }) + : await apollo(request, graphQLOptions); + + if (graphQLOptions.cors) { + setCors(response, graphQLOptions.cors); + } + + return response; + } else if ( + graphQLOptions.playgroundEndpoint && + url.pathname === graphQLOptions.playgroundEndpoint + ) { + return playground(request, graphQLOptions); + } else if (graphQLOptions.forwardUnmatchedRequestsToOrigin) { + return fetch(request); + } else { + return new Response("Not found", { status: 404 }); + } + } catch (err) { + return new Response(graphQLOptions.debug ? err : "Something went wrong", { + status: 500, + }); + } +}; + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); diff --git a/src/kv-cache.js b/src/kv-cache.js new file mode 100644 index 0000000..90e4e6b --- /dev/null +++ b/src/kv-cache.js @@ -0,0 +1,16 @@ +module.exports = class KVCache { + get(key) { + return WORKERS_GRAPHQL_CACHE.get(key); + } + + set(key, value, options) { + const opts = {}; + const ttl = options && options.ttl; + + if (ttl) { + opts.expirationTtl = ttl; + } + + return WORKERS_GRAPHQL_CACHE.put(key, value, opts); + } +}; diff --git a/src/resolvers.js b/src/resolvers.js new file mode 100644 index 0000000..1c86443 --- /dev/null +++ b/src/resolvers.js @@ -0,0 +1,13 @@ +module.exports = { + Query: { + random: async (_source, {}, { dataSources }) => { + return dataSources.senpyAPI.getRandom(); + }, + languages: async (_source, {}, { dataSources }) => { + return dataSources.senpyAPI.getLanguages(); + }, + language: async (_source, { language }, { dataSources }) => { + return dataSources.senpyAPI.getLanguage(language); + }, + }, +}; diff --git a/src/schema.js b/src/schema.js new file mode 100644 index 0000000..f5714ba --- /dev/null +++ b/src/schema.js @@ -0,0 +1,14 @@ +const { gql } = require("apollo-server-cloudflare"); + +module.exports = gql` + type Random { + language: String! + image: String! + } + + type Query { + random: Random + languages: [String] + language(language: String!): [String] + } +`; diff --git a/src/utils/setCors.js b/src/utils/setCors.js new file mode 100644 index 0000000..70773a5 --- /dev/null +++ b/src/utils/setCors.js @@ -0,0 +1,23 @@ +const setCorsHeaders = (response, config) => { + const corsConfig = config instanceof Object ? config : false; + + response.headers.set( + "Access-Control-Allow-Credentials", + corsConfig ? corsConfig.allowCredentials : "true" + ); + response.headers.set( + "Access-Control-Allow-Headers", + corsConfig ? corsConfig.allowHeaders : "application/json, Content-type" + ); + response.headers.set( + "Access-Control-Allow-Methods", + corsConfig ? corsConfig.allowMethods : "GET, POST" + ); + response.headers.set( + "Access-Control-Allow-Origin", + corsConfig ? corsConfig.allowOrigin : "*" + ); + response.headers.set("X-Content-Type-Options", "nosniff"); +}; + +module.exports = setCorsHeaders; |