Skip to content

Commit

Permalink
Merge pull request #308 from the-hideout/goon-reports
Browse files Browse the repository at this point in the history
Add goon reports query
  • Loading branch information
Razzmatazzz authored Jul 4, 2024
2 parents 792c234 + dba52e6 commit 9b22f78
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 10 deletions.
5 changes: 5 additions & 0 deletions datasources/maps.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ class MapAPI extends WorkerKV {
const { cache } = await this.getCache(context, info);
return Object.values(cache.StationaryWeapon);
}

async getGoonReports(context, info) {
const { cache } = await this.getCache(context, info);
return cache.GoonReport;
}
}

export default MapAPI;
119 changes: 119 additions & 0 deletions handlers/graphiql.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
const defaultQuery = `# Welcome to the Tarkov.dev API Playground
#
# Type queries into this side of the screen, click the Execute query
# button at the top center, the the results will appear on the right side
# of the screen.
#
# You can explore the available queries and data types by clicking the
# book icon in the upper left to open the documentation.
#
# Here's an example query to get you started:
#
{
items(lang: en) {
id
name
}
}
#
# Keyboard shortcuts:
#
# Prettify query: Shift-Ctrl-P (or press the prettify button)
#
# Merge fragments: Shift-Ctrl-M (or press the merge button)
#
# Run Query: Ctrl-Enter (or press the play button)
#
# Auto Complete: Ctrl-Space (or just start typing)
#
`;

const html = baseEndpoint => `
<!--
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
-->
<!doctype html>
<html lang="en">
<head>
<title>Tarkov.dev API Playground</title>
<link rel="shortcut icon" href="//cdn.jsdelivr.net/npm/graphql-playground-react/build/favicon.png" />
<style>
body {
height: 100%;
margin: 0;
width: 100%;
overflow: hidden;
}
#graphiql {
height: 100vh;
}
</style>
<!--
This GraphiQL example depends on Promise and fetch, which are available in
modern browsers, but can be "polyfilled" for older browsers.
GraphiQL itself depends on React DOM.
If you do not want to rely on a CDN, you can host these files locally or
include them directly in your favored resource bundler.
-->
<script
crossorigin
src="https://unpkg.com/react@18/umd/react.development.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
></script>
<!--
These two files can be found in the npm module, however you may wish to
copy them directly into your environment, or perhaps include them in your
favored resource bundler.
-->
<script
src="https://unpkg.com/graphiql/graphiql.min.js"
type="application/javascript"
></script>
<link rel="stylesheet" href="https://unpkg.com/graphiql/graphiql.min.css" />
<!--
These are imports for the GraphIQL Explorer plugin.
-->
<script
src="https://unpkg.com/@graphiql/plugin-explorer/dist/index.umd.js"
crossorigin
></script>
<link
rel="stylesheet"
href="https://unpkg.com/@graphiql/plugin-explorer/dist/style.css"
/>
</head>
<body>
<div id="graphiql">Loading...</div>
<script>
const root = ReactDOM.createRoot(document.getElementById('graphiql'));
const fetcher = GraphiQL.createFetcher({
url: '${baseEndpoint}',
});
const explorerPlugin = GraphiQLPluginExplorer.explorerPlugin();
root.render(
React.createElement(GraphiQL, {
fetcher,
defaultEditorToolsVisibility: true,
plugins: [explorerPlugin],
defaultQuery: \`${defaultQuery}\`,
}),
);
</script>
</body>
</html>
`

const headers = { 'Content-Type': 'text/html' }
const handler = (request, { baseEndpoint }) => new Response(html(baseEndpoint), { headers });

export default handler;
24 changes: 19 additions & 5 deletions index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { graphql } from 'graphql';
import { v4 as uuidv4 } from 'uuid';

import DataSource from './datasources/index.mjs';
import playground from './handlers/playground.mjs';
//import playground from './handlers/playground.mjs';
import graphiql from './handlers/graphiql.mjs';
import setCors from './utils/setCors.mjs';
import typeDefs from './schema.mjs';
import dynamicTypeDefs from './schema_dynamic.mjs';
Expand Down Expand Up @@ -199,6 +200,9 @@ async function graphqlHandler(request, env, ctx) {
}
ttl = 30 * 60;
result.warnings.push({message: `Your request does not have a "content-type" header set to "application/json". Requests missing this header are limited to resposnes that update every ${ttl/60} minutes.`});
} else if (ttl > 1800) {
// if the ttl is greater than a half hour, limit it
ttl = 1800;
}

const body = JSON.stringify(result);
Expand Down Expand Up @@ -237,17 +241,26 @@ const graphQLOptions = {
allowCredentials: 'true',
allowHeaders: 'Content-type',
allowOrigin: '*',
allowMethods: 'GET, POST',
allowMethods: 'OPTIONS, GET, POST',
},
};

export default {
async fetch(request, env, ctx) {
if (!['GET', 'POST'].includes(request.method.toUpperCase())) {
return new Response(null, {
if (!graphQLOptions.cors.allowMethods.split(', ').includes(request.method.toUpperCase())) {
const errorResponse = new Response(null, {
status: 405,
headers: { 'cache-control': 'public, max-age=2592000' },
});
setCors(errorResponse, graphQLOptions.cors);
return errorResponse;
}
if (request.method.toUpperCase() === 'OPTIONS') {
const optionsResponse = new Response(null, {
headers: { 'cache-control': 'public, max-age=2592000' },
});
setCors(optionsResponse, graphQLOptions.cors);
return optionsResponse;
}
const requestStart = new Date();
const url = new URL(request.url);
Expand All @@ -263,7 +276,8 @@ export default {
}

if (url.pathname === graphQLOptions.playgroundEndpoint) {
response = playground(request, graphQLOptions);
//response = playground(request, graphQLOptions);
response = graphiql(request, graphQLOptions);
}

if (graphQLOptions.forwardUnmatchedRequestsToOrigin) {
Expand Down
9 changes: 9 additions & 0 deletions resolvers/mapResolver.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export default {
}
return context.util.paginate(bosses, args);
},
async goonReports( obj, args, context, info) {
let reports = context.data.map.getGoonReports(context, info);
return context.util.paginate(reports, args);
},
async lootContainers(obj, args, context, info) {
let containers = context.data.map.getAllLootContainers(context, info);
return context.util.paginate(containers, args);
Expand Down Expand Up @@ -48,6 +52,11 @@ export default {
return context.util.paginate(stationaryWeapons, args);
},
},
GoonReport: {
map(data, args, context, info) {
return context.data.map.get(context, info, data.map);
}
},
HealthPart: {
bodyPart(data, args, context, info) {
return context.data.map.getLocale(data.bodyPart, context, info);
Expand Down
6 changes: 6 additions & 0 deletions schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ enum GameMode {
pve
}
type GoonReport {
map: Map
timestamp: String
}
type HealthEffect {
bodyParts: [String]!
effects: [String]!
Expand Down Expand Up @@ -1372,6 +1377,7 @@ type Query {
item(id: ID, normalizedName: String, lang: LanguageCode, gameMode: GameMode): Item
items(ids: [ID], name: String, names: [String], type: ItemType, types: [ItemType], categoryNames: [ItemCategoryName], handbookCategoryNames: [HandbookCategoryName] bsgCategoryId: String, bsgCategoryIds: [String], bsgCategory: String, lang: LanguageCode, gameMode: GameMode, limit: Int, offset: Int): [Item]!
itemCategories(lang: LanguageCode, limit: Int, offset: Int): [ItemCategory]!
goonReports(lang: LanguageCode, gameMode: GameMode, limit: Int, ofset: Int): [GoonReport]!
handbookCategories(lang: LanguageCode, limit: Int, offset: Int): [ItemCategory]!
lootContainers(lang: LanguageCode, limit: Int, offset: Int): [LootContainer]
maps(lang: LanguageCode, gameMode: GameMode, name: [String!], enemies: [String!], limit: Int, offset: Int): [Map]!
Expand Down
10 changes: 5 additions & 5 deletions utils/setCors.mjs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
const setCorsHeaders = (response, config) => {
const corsConfig = config instanceof Object ? config : false
const corsConfig = config instanceof Object ? config : {};

response.headers.set(
'Access-Control-Allow-Credentials',
corsConfig ? corsConfig.allowCredentials : 'true',
corsConfig?.allowCredentials ?? 'true',
)
response.headers.set(
'Access-Control-Allow-Headers',
corsConfig ? corsConfig.allowHeaders : 'application/json, Content-type',
corsConfig?.allowHeaders ?? 'application/json, Content-type',
)
response.headers.set(
'Access-Control-Allow-Methods',
corsConfig ? corsConfig.allowMethods : 'GET, POST',
corsConfig?.allowMethods ?? 'OPTIONS, GET, POST',
)
response.headers.set('Access-Control-Allow-Origin', corsConfig ? corsConfig.allowOrigin : '*')
response.headers.set('Access-Control-Allow-Origin', corsConfig?.allowOrigin ?? '*')
response.headers.set('X-Content-Type-Options', 'nosniff')
}

Expand Down

0 comments on commit 9b22f78

Please sign in to comment.