Newer
Older
Labyrinth / src / LabyrinthMiddleware.ts
import * as graphqlHTTP from "express-graphql";
import {buildSchema} from "graphql";
import { GameServer } from "./GameServer";
import { Direction, MazeTile } from "./MazeMap";

export const schemaDefinition = `
    enum Direction {
        none
        top
        left
        bottom
        right
    }

    """
    Representing a tile with it's possible pathways.
    """
    type MazeTileQL {
        id: String!
        paths: [Direction!]!
    }

    type Mutation {
        "Start a new game"
        startGame(userID: String!, mapID: String!): Boolean!

        "Cancels a currently running game"
        endGame(userID: String!): Boolean!

        "Moves the user to another tile and returns that tile."
        navigate(userID: String!, dir: Direction!): MazeTileQL
    }

    type Query {
        "Tells you your where you currently are and how it looks there in case you forgot."
        currentPostition(userID: String!): MazeTileQL

        "Lists currently available maps."
        listMaps: [String!]!

        "Generates a new unique user id."
        createNewUserID: String!
    }
`;

class MazeTileQL
{
    public static DirectionToString(dir:Direction): string
    {
        switch (dir) {
            case Direction.none: return "none";
            case Direction.top: return "top";
            case Direction.left: return "left";
            case Direction.bottom: return "bottom";
            case Direction.right: return "right";
        }
    }

    public static StringToDirection(dir:string): Direction
    {
        switch(dir) {
            case "none": return Direction.none;
            case "top": return Direction.top;
            case "left": return Direction.left;
            case "bottom": return Direction.bottom;
            case "right": return Direction.right;
        }
    }

    public static ConvertToMazeTileQL(tile: MazeTile): MazeTileQL
    {
        if(tile == null){
            return null;
        }
        return new MazeTileQL(tile);
    }

    public id:string;
    public paths:string[];

    constructor(tile:MazeTile)
    {
        this.id = tile.id;
        this.paths = tile.paths.map(MazeTileQL.DirectionToString);
    }
}

function createGraphQLRoot(games:GameServer)
{
    return {
        createNewUserID: () => games.createNewUserID(),
        currentPostition: ({userID}) => MazeTileQL.ConvertToMazeTileQL(games.currentPosition(userID)),
        endGame: ({userID}) => games.endGame(userID),
        listMaps: () => games.listMaps(),
        navigate: ({userID, dir}: {userID: string, dir:string}) => {
            return MazeTileQL.ConvertToMazeTileQL(games.navigate(userID, MazeTileQL.StringToDirection(dir)));
        },
        startGame: ({userID, mapID}) => games.startGame(userID, mapID),
    };
}

export function CreateLabyrinthMiddleware(graphiql:boolean, games:GameServer): graphqlHTTP.Middleware
{
    const schema = buildSchema(schemaDefinition);

    const root = createGraphQLRoot(games);

    return graphqlHTTP({
        graphiql: true,
        rootValue: root,
        schema,
    });
}