mirror of
https://github.com/MetaFam/TheGame.git
synced 2026-04-02 03:00:32 -04:00
using a remote schema instead of an action for getBoxProfile
This commit is contained in:
committed by
Hammad Jutt
parent
af728ac53d
commit
6e0f0c9b66
@@ -8,12 +8,14 @@ RUN chmod +x /wait
|
||||
ARG BACKEND_HOST
|
||||
ARG AUTH_HOOK_PATH=auth-webhook
|
||||
ARG ACTION_BASE_PATH=actions
|
||||
ARG REMOTE_SCHEMA_PATH=remote-schemas/graphql
|
||||
|
||||
ENV HASURA_GRAPHQL_DEV_MODE false
|
||||
ENV HASURA_GRAPHQL_ENABLE_TELEMETRY false
|
||||
ENV HASURA_GRAPHQL_ENABLED_LOG_TYPES startup, http-log, webhook-log, websocket-log, query-log
|
||||
ENV HASURA_GRAPHQL_AUTH_HOOK http://$BACKEND_HOST/$AUTH_HOOK_PATH
|
||||
ENV ACTION_BASE_ENDPOINT http://$BACKEND_HOST/$ACTION_BASE_PATH
|
||||
ENV REMOTE_SCHEMA_ENDPOINT http://$BACKEND_HOST/$REMOTE_SCHEMA_PATH
|
||||
ENV HASURA_GRAPHQL_MIGRATIONS_DATABASE_ENV_VAR HASURA_GRAPHQL_DATABASE_URL
|
||||
|
||||
## Migrations
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
type Query {
|
||||
getBoxProfile (
|
||||
address: String
|
||||
): BoxProfile
|
||||
}
|
||||
|
||||
|
||||
type Mutation {
|
||||
updateBoxProfile : UpdateBoxProfileResponse
|
||||
}
|
||||
@@ -17,13 +10,3 @@ type UpdateBoxProfileResponse {
|
||||
updatedProfiles : [String!]!
|
||||
}
|
||||
|
||||
type BoxProfile {
|
||||
ethereumAddress : String
|
||||
name : String
|
||||
description : String
|
||||
location : String
|
||||
job : String
|
||||
emoji : String
|
||||
imageUrl : String
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
actions:
|
||||
- name: getBoxProfile
|
||||
definition:
|
||||
kind: ""
|
||||
handler: '{{ACTION_BASE_ENDPOINT}}/getBoxProfile'
|
||||
permissions:
|
||||
- role: player
|
||||
- role: public
|
||||
- name: updateBoxProfile
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{ACTION_BASE_ENDPOINT}}/updateBoxProfile'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: player
|
||||
- name: updateBoxProfile
|
||||
definition:
|
||||
kind: synchronous
|
||||
handler: '{{ACTION_BASE_ENDPOINT}}/updateBoxProfile'
|
||||
forward_client_headers: true
|
||||
permissions:
|
||||
- role: player
|
||||
custom_types:
|
||||
enums: []
|
||||
input_objects: []
|
||||
objects:
|
||||
- name: UpdateBoxProfileResponse
|
||||
- name: BoxProfile
|
||||
- name: UpdateBoxProfileResponse
|
||||
scalars: []
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
[]
|
||||
- name: backend
|
||||
definition:
|
||||
url_from_env: REMOTE_SCHEMA_ENDPOINT
|
||||
timeout_seconds: 60
|
||||
|
||||
@@ -5,6 +5,16 @@
|
||||
- name: Player
|
||||
using:
|
||||
foreign_key_constraint_on: player_id
|
||||
remote_relationships:
|
||||
- definition:
|
||||
remote_field:
|
||||
getBoxProfile:
|
||||
arguments:
|
||||
address: $identifier
|
||||
hasura_fields:
|
||||
- identifier
|
||||
remote_schema: backend
|
||||
name: boxProfile
|
||||
select_permissions:
|
||||
- role: player
|
||||
permission:
|
||||
|
||||
1
packages/@types/express-graphql/index.d.ts
vendored
Normal file
1
packages/@types/express-graphql/index.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module 'express-graphql';
|
||||
@@ -34,7 +34,7 @@ export async function login(client, token, ethAddress) {
|
||||
query: GetMyAccount,
|
||||
variables: { eth_address: ethAddress },
|
||||
})
|
||||
.then(async (res) => {
|
||||
.then(async res => {
|
||||
if (res.data.Account.length === 0) {
|
||||
throw new Error('Impossible to fetch player, not found.');
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export async function login(client, token, ethAddress) {
|
||||
});
|
||||
setTokenInStore(token);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
.catch(async error => {
|
||||
logout(client);
|
||||
throw error;
|
||||
});
|
||||
|
||||
@@ -47,11 +47,11 @@ export const PlayerDetails: React.FC<{ player: any }> = ({ player }) => {
|
||||
variables: {
|
||||
username: usernameInput,
|
||||
},
|
||||
}).then((res) => console.log('updated username', res.data));
|
||||
}).then(res => console.log('updated username', res.data));
|
||||
}, [usernameInput, updateUsername]);
|
||||
|
||||
const updateAccounts = useCallback(() => {
|
||||
updateBoxProfiles().then((res) =>
|
||||
updateBoxProfiles().then(res =>
|
||||
console.log(
|
||||
'updated verified profiles',
|
||||
res.data.updateBoxProfile.updatedProfiles,
|
||||
@@ -72,7 +72,7 @@ export const PlayerDetails: React.FC<{ player: any }> = ({ player }) => {
|
||||
<div>
|
||||
<input
|
||||
value={usernameInput}
|
||||
onChange={(e) => setUsernameInput(e.target.value)}
|
||||
onChange={e => setUsernameInput(e.target.value)}
|
||||
/>
|
||||
<button type="button" onClick={editUserName}>
|
||||
Change username
|
||||
|
||||
@@ -65,7 +65,7 @@ export function register(config?: Config) {
|
||||
function registerValidSW(swUrl: string, config?: Config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
.then(registration => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
@@ -102,7 +102,7 @@ function registerValidSW(swUrl: string, config?: Config) {
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
@@ -112,7 +112,7 @@ function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then((response) => {
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
@@ -120,7 +120,7 @@ function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
@@ -140,10 +140,10 @@ function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
.then(registration => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch(error => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@metafam/utils": "1.0.0",
|
||||
"3box": "^1.18.1",
|
||||
"@metafam/utils": "1.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"ethers": "^4.0.46",
|
||||
"express": "^4.17.1",
|
||||
"express-graphql": "^0.11.0",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql-tools": "^6.0.15",
|
||||
"node-fetch": "^2.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import express from 'express';
|
||||
|
||||
import { asyncHandlerWrapper } from '../../lib/apiHelpers';
|
||||
|
||||
import getBoxProfile from './getBoxProfile/handler';
|
||||
import { updateBoxProfileHandler } from './updateBoxProfile/handler';
|
||||
|
||||
export const actionRoutes = express.Router();
|
||||
|
||||
actionRoutes.post('/getBoxProfile', asyncHandlerWrapper(getBoxProfile));
|
||||
|
||||
actionRoutes.post('/updateBoxProfile', asyncHandlerWrapper(updateBoxProfileHandler));
|
||||
|
||||
actionRoutes.post(
|
||||
'/updateBoxProfile',
|
||||
asyncHandlerWrapper(updateBoxProfileHandler),
|
||||
);
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
type Maybe<T> = T | null;
|
||||
|
||||
type BoxProfile = {
|
||||
ethereumAddress: string | null;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
location: string | null;
|
||||
job: string | null;
|
||||
emoji: string | null;
|
||||
imageUrl: string | null;
|
||||
};
|
||||
|
||||
type UpdateBoxProfileResponse = {
|
||||
success: boolean;
|
||||
updatedProfiles: Array<string>;
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
import { Request, Response } from 'express';
|
||||
import Box from '3box';
|
||||
|
||||
import config from '../../../config';
|
||||
import { CONFIG } from '../../../../config';
|
||||
|
||||
const handler = async (req: Request, res: Response) => {
|
||||
interface BoxProfileRequest {
|
||||
address: string,
|
||||
}
|
||||
interface BoxProfileResponse {
|
||||
ethereumAddress: string | null;
|
||||
name: string | null;
|
||||
description: string | null;
|
||||
location: string | null;
|
||||
job: string | null;
|
||||
emoji: string | null;
|
||||
imageUrl: string | null;
|
||||
}
|
||||
|
||||
const { address } = req.body.input;
|
||||
export const getBoxProfile = async (_: any, { address }: BoxProfileRequest) => {
|
||||
const boxProfile = await Box.getProfile(address);
|
||||
|
||||
if (Object.keys(boxProfile).length === 0) {
|
||||
return res.json({});
|
||||
return {};
|
||||
}
|
||||
|
||||
const parsedProfile: BoxProfile = {
|
||||
const parsedProfile: BoxProfileResponse = {
|
||||
ethereumAddress: address,
|
||||
name: boxProfile.name,
|
||||
description: boxProfile.description,
|
||||
@@ -22,7 +32,7 @@ const handler = async (req: Request, res: Response) => {
|
||||
imageUrl: getProfilePicture(boxProfile),
|
||||
};
|
||||
|
||||
return res.json(parsedProfile);
|
||||
return parsedProfile;
|
||||
};
|
||||
|
||||
function getProfilePicture(boxProfile: any) {
|
||||
14
packages/backend/src/handlers/remote-schemas/routes.ts
Normal file
14
packages/backend/src/handlers/remote-schemas/routes.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import express from 'express';
|
||||
import { graphqlHTTP } from 'express-graphql';
|
||||
|
||||
import { graphqlSchema } from './schema';
|
||||
|
||||
export const remoteSchemaRoutes = express.Router();
|
||||
|
||||
remoteSchemaRoutes.use(
|
||||
'/graphql',
|
||||
graphqlHTTP({
|
||||
schema: graphqlSchema,
|
||||
graphiql: true,
|
||||
}),
|
||||
);
|
||||
12
packages/backend/src/handlers/remote-schemas/schema.ts
Normal file
12
packages/backend/src/handlers/remote-schemas/schema.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { makeExecutableSchema } from 'graphql-tools';
|
||||
|
||||
import { typeDefs } from './typeDefs';
|
||||
import { getBoxProfile } from './resolvers/getBoxProfile/resolver';
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
getBoxProfile,
|
||||
},
|
||||
};
|
||||
|
||||
export const graphqlSchema = makeExecutableSchema({ typeDefs, resolvers });
|
||||
16
packages/backend/src/handlers/remote-schemas/typeDefs.ts
Normal file
16
packages/backend/src/handlers/remote-schemas/typeDefs.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export const typeDefs = `
|
||||
type Query {
|
||||
getBoxProfile(address: String!): BoxProfile
|
||||
}
|
||||
|
||||
type BoxProfile {
|
||||
ethereumAddress : String
|
||||
name : String
|
||||
description : String
|
||||
location : String
|
||||
job : String
|
||||
emoji : String
|
||||
imageUrl : String
|
||||
}
|
||||
|
||||
`;
|
||||
@@ -2,13 +2,21 @@ import express from 'express';
|
||||
|
||||
import { asyncHandlerWrapper } from '../lib/apiHelpers';
|
||||
import { actionRoutes } from './actions/routes';
|
||||
import { remoteSchemaRoutes } from './remote-schemas/routes';
|
||||
import { authHandler } from './auth-webhook/handler';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', function (_, res) {
|
||||
res.send('pong');
|
||||
router.get('/', function(_, res) {
|
||||
res.send('ok');
|
||||
});
|
||||
|
||||
router.get('/healthz', function(_, res) {
|
||||
res.send('ok');
|
||||
});
|
||||
|
||||
router.get('/auth-webhook', asyncHandlerWrapper(authHandler));
|
||||
|
||||
router.use('/actions', actionRoutes);
|
||||
|
||||
router.use('/remote-schemas', remoteSchemaRoutes);
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { GlobalStyle, ThemeProvider, theme } from '../src';
|
||||
import GoogleFontLoader from 'react-google-font-loader';
|
||||
|
||||
const ThemeDecorator = (storyFn) => (
|
||||
const ThemeDecorator = storyFn => (
|
||||
<ThemeProvider theme={theme}>
|
||||
<GoogleFontLoader
|
||||
fonts={[
|
||||
|
||||
@@ -16,7 +16,7 @@ export const getStaticProps = async () => {
|
||||
|
||||
const Home: React.FC<Props> = ({ pokemon }) => (
|
||||
<SimpleGrid columns={{ sm: 2, lg: 3 }} spacing={6}>
|
||||
{pokemon.map((p) => (
|
||||
{pokemon.map(p => (
|
||||
<MetaLink as={`/pokemon/${p.name}`} href="pokemon/[name]">
|
||||
<Box key={p.name}>
|
||||
<Heading style={{ textTransform: 'capitalize' }}>{p.name}</Heading>
|
||||
|
||||
@@ -38,9 +38,10 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props, { name: string }> = async (
|
||||
context,
|
||||
) => {
|
||||
export const getStaticProps: GetStaticProps<
|
||||
Props,
|
||||
{ name: string }
|
||||
> = async context => {
|
||||
const name = context.params?.name;
|
||||
const pokemon = await getPokemon(name);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user